Codeforces #441 Div1.D:(扩展Lucas)

来源:互联网 发布:淘宝网首页官网床垫 编辑:程序博客网 时间:2024/06/05 16:21

传送门

题意:
给定n,p(n1e5,q2e9),l,r,求所有长度为n的序列,满足每一位可以是A,B,C,且任意前缀A的和大于B的和,且总的AB[l,r]

题解:
http://codeforces.com/blog/entry/56135

这个转化太妙了,大概是类似找代表元的思想。

之后推导后可以用扩展Lucas求组合数了,好久没有打很不熟练啊。。

#include<bits/stdc++.h>using namespace std;inline int rd(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;} typedef pair<int,int> pii;const int Maxn=1e5+50;vector<pii>fac;int n,p,l,r,vis[Maxn][35],v[35],fac2[Maxn][35];pii fac1[Maxn][35];long long ans;inline int power(int a,int b,int mod){    int rs=1;    for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)rs=1ll*rs*a%mod;    return rs;} inline int calc_inv(int A,int id);inline pii calc_fac(int A,int id){    if(!A)return make_pair(0,1);    if(vis[A][id])return fac1[A][id];    vis[A][id]=1;int bl=A/fac[id].first;    int t1=fac2[bl*fac[id].first][id];    int t2=1ll*fac2[A][id]*calc_inv(fac2[bl*fac[id].first][id],id)%v[id];    t1=1ll*t1*t2%v[id];    pii t3=calc_fac(bl,id);    return fac1[A][id]=make_pair(t3.first+bl,1ll*t1*t3.second%v[id]);} inline void exgcd(int A,int B,long long &x,long long &y){    if(!B){        x=1;y=0;return;    }    exgcd(B,A%B,x,y);    long long t=x;    x=y;    y=t-A/B*y;}inline int calc_inv(int A,int id){    long long x,y;    exgcd(A,v[id],x,y);    x%=v[id];x+=v[id];x%=v[id];    return x;}inline void merge(int &A,int &B,int C,int D){    long long k1,k2;    exgcd(A,C,k1,k2);    k1%=C;k1+=C;k1%=C;    k1=k1*(D-B);    k1%=C;k1+=C;k1%=C;    B=(k1*A+B);    A=A*C;B%=A; } inline int calc(int A,int B){    if(B<0)return 0;    if(!B)return 1;    int now=1,rs=0;    for(int i=0;i<fac.size();++i){        pii t1=calc_fac(A,i),t2=calc_fac(B,i),t3=calc_fac(A-B,i);         t1.first-=(t2.first+t3.first);        t1.second=1ll*t1.second*calc_inv(t2.second,i)%v[i]*calc_inv(t3.second,i)%v[i];        for(int j=1;j<=t1.first;j++)t1.second=1ll*fac[i].first*t1.second%v[i];        merge(now,rs,v[i],t1.second);    }    return rs;}int main(){    n=rd(),p=rd(),l=rd(),r=rd();int tt=p;    for(int i=2;i*i<=tt;++i){        if(!(tt%i)){            pii t=make_pair(i,0);v[fac.size()]=1;            while(!(tt%i))tt/=i,++t.second,v[fac.size()]*=i;            fac.push_back(t);        }    }    if(tt!=1)v[fac.size()]=tt,fac.push_back(make_pair(tt,1));    for(int i=0;i<fac.size();i++){        fac2[0][i]=1;        for(int j=1;j<=n;j++){            fac2[j][i]=1ll*fac2[j-1][i]*(j%fac[i].first?j:1)%v[i];         }    }    for(int C=0;C<=n;++C){        r=min(r,n-C);if(r<l)break;        int rs=n-C,tp=calc(n,C);        int L=l+((l&1)!=(rs&1)),R=r-((r&1)!=(rs&1));         if(L>R)continue;        ans+=calc(rs,(rs-L)/2)*1ll*tp%p;        ans-=calc(rs,(rs-R-2)/2)*1ll*tp%p;        ans%=p;ans+=p;ans%=p;     }    cout<<ans<<endl;}