bzoj4403 序列统计
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。
正解:组合数学+$lucas$定理。
设$m=r-l+1$,打表后可发现$Ans=C_{n+m}^{m}-1$。
然后用卢卡斯定理:$lucas_{n}^{m}=C_{n mod p}^{m mod p}*lucas_{n/p}^{m/p}$。
要预处理$[0,p-1]$的阶乘和逆元,逆元的线性求法:$inv_{i}=-(p/i)*inv_{p mod i}$。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define rhl (1000003LL) 15 #define N (1000010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 ll fac[N],inv[N],n,m,l,r; 24 25 il ll cm(RG ll n,RG ll m){ 26 if (n<m) return 0; 27 return fac[n]*inv[fac[m]]%rhl*inv[fac[n-m]]%rhl; 28 } 29 30 il ll lucas(RG ll n,RG ll m){ 31 if (m==0) return 1; 32 return cm(n%rhl,m%rhl)*lucas(n/rhl,m/rhl)%rhl; 33 } 34 35 il void pre(){ 36 fac[0]=fac[1]=inv[1]=1; 37 for (RG ll i=2;i<rhl;++i){ 38 fac[i]=fac[i-1]*i%rhl; 39 inv[i]=(rhl-rhl/i)*inv[rhl%i]%rhl; 40 } 41 return; 42 } 43 44 il void work(){ 45 scanf("%lld%lld%lld",&n,&l,&r); m=r-l+1; 46 printf("%lld\n",(lucas(n+m,m)+rhl-1LL)%rhl); return; 47 } 48 49 int main(){ 50 File("lucas"); 51 pre(); RG ll T; cin>>T; 52 while (T--) work(); 53 return 0; 54 }