BZOJ 4403序列統計

ppllxx發表於2024-04-15

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 $ 。

  • 線性求逆元,求階乘逆元。

相關文章