【BZOJ 4403】序列统计

本文介绍了一种利用组合数学原理解决特定类型问题的方法,并通过一个具体的编程实例详细展示了如何运用Lucas定理来高效求解这类问题。文章还提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目链接。比较简洁的题意,其实题目也不难。首先总共会有R-L+1=m个数可以选择,我们假设当前序列的长度为k,那么每种数选择的数量是x_i则有:

                                               x_1+x_2+x_3....x_m=k

就是求一下这个序列的非负整数解有多少个,显然有C(m+k-1,m-1)。然后答案就是:

                                              \sum_{k=1}^{n}C(m+k-1,m-1)

然后采用:C(m,n-1)+C(m-1,n-1)=C(m,n)这个式子化简即可达到:ans=C(m+R-L+1,R-L+1).

求解这个数mod p的值,p是一个不是很大的素数,直接Lucas定理解决。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 1e6 + 3;
LL fac[mod + 10];
LL exgcd(LL a, LL b, LL& x, LL& y)
{
	if (!b)
	{
		x = 1;
		y = 0;
		return a;
	}
	LL ret = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return ret;
}

LL Inv(LL a, LL mod)
{
	LL x, y;
	LL ret = exgcd(a, mod, x, y);
	if (ret == 1) return (x % mod + mod) % mod;
	return -1;
}

LL C(int n, int m, int mod)
{
	if (m > n) return 0;
	LL ret = fac[n];
	ret *= Inv((fac[m] * fac[n - m]) % mod, mod);
	return ret % mod;
}
LL Lucas(LL n, LL m, LL mod)
{
	if (m == 0) return 1;
	return C(n % mod, m % mod, mod) * Lucas(n / mod, m / mod, mod) % mod;
}
void init()
{
	fac[0] = 1;
	for (int i = 1; i <= mod; i++) fac[i] = (fac[i - 1] * i) % mod;//预处理阶乘
}
int main()
{
	int T;
	scanf("%d", &T);
	init();
	while (T--) {
		int n, l, r;
		scanf("%d%d%d", &n, &l, &r);
		int m = (r - l + 1) - 1;
		LL ans = Lucas(m + n + 1, m + 1,mod) - 1;
		ans = (ans %mod + mod) % mod;
		printf("%lld\n", ans);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值