首页 > 代码库 > 数学的东西(BZOJ1951)

数学的东西(BZOJ1951)

#include <cstdio>#define LL long long   LL finmo=999911659;  LL fac[4][40001],inv[4][40001];  LL tmp[4],rev[4];  LL n,g,x,y;  const LL mo[4]={2,3,4679,35617};  LL qpow(LL bas,LL pow,LL mo){      LL ret=1;      for (;pow;bas*=bas,bas%=mo,pow=pow>>1){        if (pow&1) ret*=bas,ret%=mo;    }    return(ret);  }//快速幂    LL C(LL t1,LL t2,LL mopo){      if (t2>t1) return(0);      return((fac[mopo][t1]*inv[mopo][t2])%mo[mopo]*inv[mopo][t1-t2]%mo[mopo]);  }//组合数    LL lucas(int t1,int t2,int mopo){      LL ret=1;      while(t1||t2){        ret*=C(t1%mo[mopo],t2%mo[mopo],mopo);ret%=mo[mopo];      t1/=mo[mopo];t2/=mo[mopo];        }    return(ret);  }//lucas定理    LL solve(LL num){      for (int i=0;i<=3;i++) tmp[i]=lucas(n,num,i);    LL ret=0;    for (int i=0;i<=3;i++)       ret+=tmp[i]*(finmo/mo[i])*rev[i],ret%=finmo-1;    return(ret);      }//线性同余方程的解    void exgcd(LL a,LL b,LL &x,LL &y){      if (b==0){        x=1LL;y=0LL;return;        }    exgcd(b,a%b,x,y);    LL t=x;x=y;y=t-(a/b)*y;  }//扩展欧几里得  int main(){            scanf("%lld%lld",&n,&g);      for (int i=0;i<=3;i++){        fac[i][0]=1;inv[i][0]=1;      for (int j=1;j<mo[i];j++) {fac[i][j]=(fac[i][j-1]*j)%mo[i];inv[i][j]=qpow(fac[i][j],mo[i]-2,mo[i]);}        }    for (int i=0;i<=3;i++){      exgcd(finmo/mo[i],mo[i],x,y);      rev[i]=(x%mo[i]+mo[i])%mo[i];        }        LL ans=0;    for (int i=1;i*i<=n;i++)     if (n%i==0){      ans+=solve(i);ans%=finmo-1;          if (n/i!=i) ans+=solve(n/i),ans%=finmo-1;    }        LL finans=qpow(g,ans,finmo);    if (g==999911659)printf("0\n");else printf("%lld\n",finans);  }

 

数学的东西(BZOJ1951)