bzoj4403: 序列统计
Description
给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。
Input
输入第一行包含一个整数T,表示数据组数。
第2到第T+1行每行包含三个整数N、L和R,N、L和R的意义如题所述。
1≤N,L,R≤10^9,1≤T≤100,输入数据保证L≤R。
Output
输出包含T行,每行有一个数字,表示你所求出的答案对10^6+3取模的结果。
Sample Input
2
1 4 5
2 4 5
1 4 5
2 4 5
Sample Output
2
5
//【样例说明】满足条件的2个序列为[4]和[5]。
5
//【样例说明】满足条件的2个序列为[4]和[5]。
题目所求的是可重复组合
公式:$H(n,r)=C(n+r-1,r)$
将公式套到本题数据上:$ans=\sum_{i=1}^{n}H(r-l+1,i)=\sum_{i=1}^{n}C(r-l+i,i)$
为了便于化简,我们设$k=r-l$
那么$ans=\sum_{i=1}^{n}C(k+i,i)=\sum_{i=1}^{n}C(k+i,k)$
把式子展开
$=C(k+1,k)+C(k+2,k)+C(k+3,k)+...+C(k+n,k)$
添上一个$C(k+1,k+1)-1$,得:
$=C(k+1,k+1)+C(k+1,k)+C(k+2,k)+C(k+3,k)+...+C(k+n,k)-1$
套上杨辉三角公式$C(i,j)=C(i-1,j)+C(i-1,j-1)$
$=C(k+2,k+1)+C(k+2,k)+C(k+3,k)+...+C(k+n,k)-1$
$=C(k+n+1,k+1)-1$
用$Lucas$求解。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define re register 5 using namespace std; 6 typedef long long ll; 7 int min(int a,int b){return a<b?a:b;} 8 const int p=1e6+3; 9 int t,n,l,r;ll fac[p+2]; 10 ll Pow(ll x,int y){ 11 ll res=1; 12 for(;y;y>>=1,x=x*x%p) 13 if(y&1) res=res*x%p; 14 return res; 15 } 16 ll C(int a,int b){ 17 return a<b?0:fac[a]*Pow(fac[b]*fac[a-b]%p,p-2)%p; 18 } 19 ll lucas(int a,int b){ 20 return b?lucas(a/p,b/p)*C(a%p,b%p)%p:1; 21 } 22 int main(){ 23 scanf("%d",&t); fac[0]=1; 24 for(re int i=1;i<=p;++i) fac[i]=fac[i-1]*i%p; 25 while(t--){ 26 scanf("%d%d%d",&n,&l,&r); int k=r-l; 27 printf("%lld\n",(lucas(n+k+1,min(n,k+1))-1+p)%p); 28 }return 0; 29 }