【BZOJ】【lucas定理】4403: 序列统计

m=RL+1 m = R − L + 1 如果长度确定为 n n ,相当于求 mi=1xi=n ∑ i = 1 m x i = n ,用插板法得答案为 (n+m1m1) ( n + m − 1 m − 1 ) ,然后就是一波骚操作:

(xy)=(x1y)+(x1y1) ( x y ) = ( x − 1 y ) + ( x − 1 y − 1 )

i=1n(i+m1m1)=(n+m1n)+(n1+m1n1)+...+(m+12)+(m1)+(m0)1=i=1n(i+m1m1)=(n+m1n)+(n1+m1n1)+...+(m+12)+(m+11)1=(n+mn)1 ∑ i = 1 n ( i + m − 1 m − 1 ) = ( n + m − 1 n ) + ( n − 1 + m − 1 n − 1 ) + . . . + ( m + 1 2 ) + ( m 1 ) + ( m 0 ) − 1 = ∑ i = 1 n ( i + m − 1 m − 1 ) = ( n + m − 1 n ) + ( n − 1 + m − 1 n − 1 ) + . . . + ( m + 1 2 ) + ( m + 1 1 ) − 1 = ( n + m n ) − 1

由于范围较大,但是注意到模数是质数,直接用 lucas l u c a s 定理就可以了。

代码

#include
#include
#include
using namespace std;
typedef long long LL;
const int tt=1000003;
int T,f[tt+6],inv[tt+6];
int C(int x,int y){if(x<y)return 0;return (LL)f[x]*inv[y]%tt*inv[x-y]%tt;}
int lucas(int x,int y){if(!y)return 1;return (LL)C(x%tt,y%tt)*lucas(x/tt,y/tt)%tt;}
int main(){
    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
    f[0]=inv[0]=inv[1]=1;
    for(int i=1;i<=tt;i++)f[i]=(LL)f[i-1]*i%tt;
    for(int i=2;i<=tt;i++)inv[i]=(tt-(LL)tt/i*inv[tt%i]%tt)%tt;
    for(int i=2;i<=tt;i++)inv[i]=(LL)inv[i-1]*inv[i]%tt;
    scanf("%d",&T);
    for(int n,l,r;T;T--)scanf("%d%d%d",&n,&l,&r),printf("%d\n",(lucas(r-l+1+n,n)-1+tt)%tt);
    return 0;
}

你可能感兴趣的:(BZOJ,lucas定理)