Bzoj4403 序列统计

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 566  Solved: 270

Description

给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。

Input

输入第一行包含一个整数T,表示数据组数。第2到第T+1行每行包含三个整数N、L和R,N、L和R的意义如题所述。

Output

输出包含T行,每行有一个数字,表示你所求出的答案对106+3取模的结果。

Sample Input

21 4 52 4 5

Sample Output

25

HINT

提示

【样例说明】满足条件的2个序列为[4]和[5]。

【数据规模和约定】对于100%的数据,1≤N,L,R≤10^9,1≤T≤100,输入数据保证L≤R。

Source

 
 
数学问题 组合数 lucas定理
 
设M=R-L+1,即可用的数值的数量
对于任意一个序列,将第i个数+i,那么原来的问题就转化为了长度为N(N=1 to n)的在[l+1,r+N]区间以内的单调递增的序列的个数。
对于每个确定的N,答案为
$ C_{N+M-1}^{N}  = C_{N+M-1}^{M-1} $
所以长度为1到N之间,满足要求的序列个数为
$sum C_{N+M-1}^{N} = sum C_{N+M-1}^{M-1}$
尝试化简这个序列:
根据组合数的递推性质$ C(n,m)=C(n-1,m)+C(n-1,m-1) $
$ ans=sum_{i=1}^{N} C_{i+M-1}^{M-1} extrm +C_{M}^{M}-1 $
$ ans=sum_{i=2}^{N} C_{i+M-1}^{M-1} extrm +C_{M+1}^{M}-1 $
$ ans=sum_{i=3}^{N} C_{i+M-1}^{M-1} extrm +C_{M+2}^{M}-1 $
以此类推
$ ans=C_{M+N}^{M}-1 $
 
得到答案就是C(n+m,m)-1,用lucas定理算出来即可
 
蜜汁WA2次之后直接把int全开成LL,就蜜汁过了
 
 
 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 using namespace std;
10 const int mod=1e6+3;
11 const int mxn=1000010;
12 int read(){
13     int x=0,f=1;char ch=getchar();
14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 LL pw[mxn],inv[mxn];
19 void init(){
20     pw[0]=1;inv[1]=1;
21     pw[1]=1;inv[0]=1;
22     for(int i=2;i<mxn;i++){
23         pw[i]=(LL)pw[i-1]*i%mod;
24         inv[i]=((-(mod/i)*(LL)inv[mod%i])%mod+mod)%mod;
25     }
26     return;
27 }
28 LL calc(int n,int m){
29     if(n<m)return 0;
30     int res=(LL)pw[n]*inv[pw[m]]%mod*inv[pw[n-m]]%mod;
31     return res;
32 }
33 LL lucas(LL n,LL m){
34     if(!m)return 1;
35     return calc(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
36 }
37 int T,n,m,L,R;
38 int main(){
39     int i,j;
40     T=read();
41     init();
42     while(T--){
43         n=read();L=read();R=read();
44         m=R-L+1;
45         int ans=lucas((LL)n+m,m)-1;
46         if(ans<0)ans+=mod;
47         printf("%d
",ans);
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/SilverNebula/p/6602153.html