BZOJ 4403序列统计

BZOJ 4403序列统计

解析

序列满足单调不降序列,所以每个数可以选多次,我们可以把不同位置的同一个数看成多个,

这样 把区间为 \([L,R]\) 中的每一个数加上 \(i\) , 得到的区间大小为 \([L+1,R+n]\) , 也就是从 \(R-L+n\) 个数中选 \(n\) 个。

\[\begin{aligned}&{ \sum^n_{i=1}C^{i}_{R-L+i} } \\ =&{ \sum^n_{i=1}C^{R-L}_{R-L+i} } \end{aligned} \]

暴力会 \(\mathbb{T}\) , 我们可以把上述式子化简,由杨辉三角可易得:

\[{\begin{aligned} C^{m}_n=C^m_{n-1}+C^{m-1}_{n-1}\end{aligned}} \]

\(\therefore\) 加一项 \(\displaystyle {C^{R-L+1}_{R-L+1}}\) 再减去,式子可以压缩为:

\[{C^{R-L+n+1}_{R-L+1}} \]

于是,终于可以快乐 \(\mathbb {Lucas}\) 啦!

#include<bits/stdc++.h>
using namespace std;
const int mod = 1000003;
typedef long long LL;
LL n,l,r,t,len;
LL fac[mod+10],inv[mod+10];
LL C(LL x,LL y,LL p)
{
	if(x<y) return 0;
	return (fac[x]*inv[y]%p*inv[x-y]%p);
}
LL Lucas(LL x,LL y,LL p)
{
	if(y==0) return 1;
	return (C(x%p,y%p,p)*Lucas(x/p,y/p,p))%p;
}
void init()
{
	fac[0]=1;
	for(int i=1;i<mod;i++) fac[i]=fac[i-1]*i%mod;
	inv[1]=1;
	for(int i=2;i<mod;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	inv[0]=1;
	for(int i=1;i<mod;i++) inv[i]=(inv[i-1]*inv[i])%mod;	
	return;
}
int main()
{
	init();
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld%lld%lld",&n,&l,&r);
		len=r-l;
		printf("%lld\n",(Lucas(len+n+1,len+1,mod)-1+mod)%mod);
	}
	return 0;
}

注意

  • \(C^x_y\) 当 $x > y $ 时, 等于 $ 0 $ 。

  • 线性求逆元,求阶乘逆元。

posted @ 2024-04-15 17:45  ppllxx_9G  阅读(14)  评论(0编辑  收藏  举报