集各比较重要的数论定理于一身的题
如果没学过快速幂、费马小定理、lucas定理、中国剩余定理的,请出门右转文化课,OI不适合你,请出门左转自行百度/google
学完了这题就是大傻逼题了
另外注意特判G=P时,费马小定理不成立,直接输出0
#include <iostream> #include <cmath> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #define ll long long using namespace std; const int P0=999911659; const int P1=999911658; const int p[4]={35617,4679,3,2}; int pow(int x,int y,int P){ int ret=1; while (y){ if (y&1) ret=(ll)ret*x%P; x=(ll)x*x%P; y=y>>1; } return ret; } int inv(int x,int P){return pow(x,P-2,P);} int fact[66666]; int C(int n,int m,int P){ if (n<m) return 0; return (ll)fact[n]*inv(fact[n-m],P)%P*inv(fact[m],P)%P; } int lucas(int n,int m,int P){ if (!n&&!m) return 1; return (ll)lucas(n/P,m/P,P)*C(n%P,m%P,P)%P; } int n,G; int main(){ scanf("%d%d",&n,&G); if (G==P0){puts("0");return 0;} for (int i=fact[0]=1;i<=p[0];++i) fact[i]=(ll)fact[i-1]*i%P1; int tot=0; for (int k=0;k<4;++k){ int now=0; for (int i=1;i*i<=n;++i)if (n%i==0){ (now+=lucas(n,i,p[k]))%=p[k]; if (n/i!=i) (now+=lucas(n,n/i,p[k]))%=p[k]; } (tot+=(ll)now*(P1/p[k])%P1*inv(P1/p[k],p[k])%P1)%=P1; } printf("%d ",pow(G,tot,P0)); return 0; }