HDU 5728 PowMod
具体推导过程可以看这篇博客..我是看这个看懂的,其余的人都是直接给的结果..
http://blog.csdn.net/wust_zzwh/article/details/51966450
分两步:1.求k,2.求答案。
对于第二步:即bzoj 3884,http://blog.csdn.net/skywalkert/article/details/43955611 看了这个就会了。
对于第一步:请看http://blog.csdn.net/wust_zzwh/article/details/51966450 详细推导过程。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const LL mod=1000000007; const int maxn=10000010; int phi[maxn],prime[maxn],sz; bool check[maxn]; LL sumPhi[maxn],a[maxn],cnt; LL n,m,P,k,ans; LL pow(LL a,LL b,LL p) { LL res=1; a%=p; while(b) { if(b&1) res=(res*a)%p; a=(a*a)%p, b/=2; } return res; } LL f(LL p) { if(p==2) return k%2; return pow(k,f(phi[p])+(LL)phi[p],p); } LL get(int pos,LL x,LL y) { if(x==1) return sumPhi[y]; if(y==1) return phi[x]; if(y<1) return 0; return (phi[a[pos]]*get(pos-1,x/a[pos],y)%mod+get(pos,x,y/a[pos])%mod)%mod; } void Eorue() { phi[1]=1; sz=0; for(int i=2;i<maxn;i++) { if(!check[i]) { phi[i]=i-1; prime[sz++]=i; } for(int j=0;j<sz;j++) { if(i*prime[j]>=maxn)break; check[i*prime[j]]=true; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j];break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } sumPhi[0]=0; for(int i=1;i<maxn;i++) sumPhi[i]=(sumPhi[i-1]+(LL)phi[i])%mod; } void fun(LL x) { cnt=0; for(int i=0;i<sz;i++) { if(x==1) break; if(x%(LL)prime[i]==0) { a[cnt++]=(LL)prime[i]; x=x/(LL)prime[i]; } } } int main() { Eorue(); while(~scanf("%lld%lld%lld",&n,&m,&P)) { fun(n);//质因数分解 k=get(cnt-1,n,m);//计算k ans=f(P); printf("%lld\n",ans); } return 0 ; }