BZOJ 4403 序列统计(Lucas)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4403
【题目大意】
给定三个正整数N、L和R,统计长度在1到N之间,
元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。
【题解】
我们用插板法,在设m=R-L+1,答案等价于在n+m个球里面拿出m个球变成插板,
那么答案就是拿掉这些插板之后的分堆。
【代码】
#include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const int N=1000010; const LL mod=1000003; namespace Lucas{ LL f[N],rf[N]; LL mul(LL x,LL y,LL P){return (x*y-(LL)(x/(long double)P*y+1e-3)*P+P)%P;} LL pow(LL a,LL b,LL P){LL t=1;for(;b;b>>=1,a=mul(a,a,P))if(b&1)t=mul(t,a,P);return t;} void Initialize(int n){ f[0]=1;for(int i=1;i<n;i++)f[i]=f[i-1]*i%n; rf[n-1]=pow(f[n-1],n-2,n); for(int i=n-1;i;i--)rf[i-1]=rf[i]*i%n; } LL C(int n,int m,int mod){ if(m>n||m<0||n<0)return 0; return f[n]*rf[m]%mod*rf[n-m]%mod; } LL lucas(LL n,LL m,LL P){ if(n<m)return 0; if(!m||n==m)return 1; return C(n%P,m%P,P)*lucas(n/P,m/P,P)%P; } } int T; LL n,l,r; int main(){ scanf("%d",&T); using namespace Lucas; Initialize(mod); while(T--){ scanf("%lld%lld%lld",&n,&l,&r); printf("%lld\n",(lucas(n+r-l+1,r-l+1,mod)+mod-1)%mod); }return 0; }
愿你出走半生,归来仍是少年