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

Sample Output

2
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 }
View Code

 

 
posted @ 2018-11-05 10:31  kafuuchino  阅读(190)  评论(0编辑  收藏  举报