题目地址:ZOJ 2674
题意:已知a1=p,an+1=p^an,bn=an(mod m!),给定p和m,求bn的极限。
思路:我们知道
我们设
那么存在
然后y又可以看作是x的子问题,然后一直递归可以求得最后的结果。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-6;
using namespace std;
const int Maxn=1e6+10;
int Euler(int n)
{
int m=floor(sqrt(n+0.5));
int ans=n;
for(int i=2;i<=m;i++){
if(n%i==0){
ans=ans/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
ans=ans/n*(n-1);
return ans;
}
LL Mul(LL a,LL b,LL mod)
{
LL res=0;
while(b>0){
if(b&1) res=(res+a)%mod;
b>>=1;
a=(a+a)%mod;
}
return res;
}
LL modxp(LL a,LL b,LL mod)
{
LL res=1;
while(b>0){
if(b&1) res=Mul(res,a,mod);
b>>=1;
a=Mul(a,a,mod);
}
return res;
}
LL Solve(LL a,LL mod)
{
if(mod==1) return 0;
LL t=Euler(mod);
return modxp(a,t,mod)%mod*modxp(a,Solve(a,t),mod)%mod;
}
int main()
{
LL a,m;
LL fac;
int flag=1;
while(~scanf("%lld %lld",&a,&m)){
if(!flag) puts("");
else flag=0;
fac=1;
for(int i=2;i<=m;i++)
fac*=i;
printf("%lld\n",Solve(a,fac)%fac);
}
return 0;
}