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 }

 

posted @ 2017-03-15 09:57  wfj_2048  阅读(215)  评论(0编辑  收藏  举报