集各比较重要的数论定理于一身的题
如果没学过快速幂、费马小定理、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\n",pow(G,tot,P0));
return 0;
}