序列统计

序列统计

有T组询问,求数字在L,R间长度为1~N的不降序列方案数数(mod 10^6+3)
,1≤N,L,R≤10^9,1≤T≤100

显然可以令(R=R-L+1),不会影响结果,而不降序列正好与可重组合一一对应,因为一种可重组合有且仅有一种一一对应的方案,根据下标公式,于是不难得知答案应为

[C_{R-1+1}^{R-1}+C_{R-1+2}^{R-1}+...+C_{R-1+N}^{R-1}= ]

[C_R^R+C_{R-1+1}^{R-1}+C_{R-1+2}^{R-1}+...+C_{R-1+N}^{R-1}-C_{R}^R= ]

[C_{R+N}^R-1 ]

用lucus定理套公式即可。

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define ll long long
#define yyb 1000003
using namespace std;
int jc[yyb],jv[yyb];
il void prepare();
il int pow(int,int),lucus(int,int),
    C(int,int);
int main(){
    int t,n,l,r;
    scanf("%d",&t),prepare();
    while(t--)scanf("%d%d%d",&n,&l,&r),r-=l-1,
                  printf("%d
",(lucus(r+n,r)-1+yyb)%yyb);
    return 0;
}
il int lucus(int n,int r){
    int ans(1);
    while(r)ans=(ll)ans*C(n%yyb,r%yyb)%yyb,
                n/=yyb,r/=yyb;
    return ans;
}
il int C(int n,int r){
    if(n<r)return 0;
    return (ll)jc[n]*jv[r]*jv[n-r]%yyb;
}
il int pow(int x,int y){
    int ans(1);
    while(y){
        if(y&1)ans=(ll)ans*x%yyb;
        x=(ll)x*x%yyb,y>>=1;
    }return ans;
}
il void prepare(){
    int i;
    for(i=jc[0]=1;i<yyb;++i)
        jc[i]=(ll)jc[i-1]*i%yyb;
    --i,jv[i]=pow(jc[i],yyb-2),jv[0]=1;
    while(i>1)jv[i-1]=(ll)jv[i]*i%yyb,--i;
}
原文地址:https://www.cnblogs.com/a1b3c7d9/p/10788692.html