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 $ 。
-
線性求逆元,求階乘逆元。