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
",(lucas(n+r-l+1,r-l+1,mod)+mod-1)%mod);
    }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/bzoj4403.html