BZOJ 1951 Lucas定理+CRT
思路:
枚举约数
套个裸的Lucas+CRT就完了...
//By SiriusRen #include <cmath> #include <cstdio> using namespace std; #define int long long const int M=999911658,N=35617; void exgcd(int a,int b,int &x,int &y){ if(!b){x=1,y=0;return;} exgcd(b,a%b,x,y); int temp=x;x=y;y=temp-a/b*y; } int CRT(int *a,int *m,int num){ int ans=0; for(int i=1;i<=num;i++){ int x,y; exgcd(M/m[i],m[i],x,y); ans=(ans+M/m[i]*x%M*a[i])%M; }return ans; } int power(int x,int y){ int ans=1; while(y){ if(y&1)ans=ans*x%(M+1); x=x*x%(M+1),y>>=1; }return ans; } int m[5]={0,2,3,4679,35617},n,g,fac[N],inv[N],sqr,s[N],top,ans[5],T; int C(int x,int y){ if(x<y)return 0; if(x<m[T]&&y<m[T])return fac[x]*inv[y]%m[T]*inv[x-y]%m[T]; return C(x/m[T],y/m[T])*C(x%m[T],y%m[T])%m[T]; } signed main(){ scanf("%lld%lld",&n,&g),sqr=sqrt(n); for(int i=1;i<sqr;i++)if(n%i==0)s[++top]=i,s[++top]=n/i; if(sqr*sqr==n)s[++top]=sqr; if(n%sqr==0&&sqr*sqr!=n)s[++top]=sqr,s[++top]=n/sqr; fac[1]=fac[0]=inv[1]=inv[0]=1; for(T=1;T<=4;T++){ for(int i=2;i<m[T];i++)fac[i]=fac[i-1]*i%m[T]; for(int i=2;i<m[T];i++)inv[i]=(m[T]-m[T]/i)*inv[m[T]%i]%m[T]; for(int i=2;i<m[T];i++)inv[i]=inv[i]*inv[i-1]%m[T]; for(int i=1;i<=top;i++)ans[T]=(ans[T]+C(n,s[i]))%m[T]; } printf("%lld\n",power(g,CRT(ans,m,4)+M)); }