BZOJ4403: 序列统计

来源:互联网 发布:几何网络是什么意思 编辑:程序博客网 时间:2024/06/06 20:52

BZOJ4403

求非降序列可以考虑将每一个位置加上i,变成求严格上升序列。
那么长度为i,范围在lr之间的方案数为Cii+rl
M=rl+1

ans=i=1nCiM+i1
=C1M+C2M+1+C3M+2++CNM+N1
=1+C0M+C1M+C2M+1+C3M+2++CNM+N1
=CNM+N1

因为n,m较大,用Lucas定理解决。

如果要预处理逆元,要用线性方法。。试着用费马小定理预处理T掉了。
因为T只有100,每次计算也只有log级别,所以不预处理逆元会更快。

【代码】

不预处理。每次直接算逆元。360ms

#include <cstdio>#include <iostream>#include <algorithm>#define N 1000000#define INF 0x7fffffff#define mod 1000003using namespace std;typedef long long ll;typedef pair<int,int> pa;int read(){    int x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}int T,n,m,l,r;int Fac[N];int Qpow(int x,int y){    int rtn=1;    while(y){        if(y&1) rtn=1LL*x*rtn%mod;        x=1LL*x*x%mod;y>>=1;    }    return rtn;}int Lucas(int x,int y){    if(x<y) return 0;    if(x<mod&&y<mod) return 1LL*Fac[x]*Qpow(1LL*Fac[y]*Fac[x-y]%mod,mod-2)%mod;    return 1LL*Lucas(x/mod,y/mod)*Lucas(x%mod,y%mod)%mod;}int main(){    T=read();    Fac[0]=1;    for(register int i=1;i<mod;i++) Fac[i]=(1LL*Fac[i-1]*i)%mod;    while(T--)    {        n=read(),l=read(),r=read();        m=r-l+1;        printf("%d\n",(Lucas(n+m,n)-1+mod)%mod);    }    return 0;}

线性预处理逆元 1272ms

#include <cstdio>#include <iostream>#include <algorithm>#define N 1000005#define INF 0x7fffffff#define mod 1000003using namespace std;typedef long long ll;typedef pair<int,int> pa;int read(){    int x=0,f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    return x*f;}int T,n,m,l,r;ll Inv[N],Fac[N];ll Qpow(int x,int y){    ll rtn=1;    while(y){        if(y&1) rtn=1LL*x*rtn%mod;        x=1LL*x*x%mod;y>>=1;    }    return rtn;}void Pre_Work(){    Inv[0]=Fac[0]=Inv[1]=1;    for(int i=1;i<mod;i++) Fac[i]=(Fac[i-1]*i)%mod;    for(int i=2;i<mod;i++) Inv[i]=(mod-mod/i)*Inv[mod%i]%mod;    for(int i=1;i<mod;i++) Inv[i]=(Inv[i]*Inv[i-1])%mod;}ll Lucas(int x,int y){    if(x<y) return 0;    if(x<mod&&y<mod) return Fac[x]*Inv[y]%mod*Inv[x-y]%mod;    return Lucas(x/mod,y/mod)*Lucas(x%mod,y%mod)%mod;}int main(){    T=read();    Pre_Work();    while(T--)    {        n=read(),l=read(),r=read();        m=r-l+1;        printf("%lld\n",(Lucas(n+m,n)-1+mod)%mod);    }    return 0;}
原创粉丝点击