题目要求算出幂塔函数 a^ ( a ^ ( a ^ (…)))共 b 个 a 乘幂的结果模m的值。由于指数会非常大,使用欧拉定理递归降幂。
但是不能直接使用,欧拉降幂有三种方式(在不同条件下)
所以需要每次判断a与目前模数p是否互质,以及判断指数b与目前的模数之前的大小关系,来判断每次使用哪种方式递归降幂。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#pragma GCC optimize(3) //2
using namespace std;
typedef long long ll;
ll get_phi(ll n)
{
ll res=n;
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
res=res/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1)
res=res/n*(n-1);
return res;
}
ll q_pow(ll a,ll b,ll p)
{
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
ll f(ll a,ll cnt,ll p)
{
if(cnt==0||p==1)
return 1;
ll phi=get_phi(p);
ll b=f(a,cnt-1,phi);
if(__gcd(a,p)==1) //第一种
return q_pow(a,b%phi,p);
else if(b&&b<phi) //第二种(注意b为0的时候不能用第二种!)
return q_pow(a,b,p);
else //第三种
return q_pow(a,b%phi+phi,p);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll a,b,p;
scanf("%lld%lld%lld",&a,&b,&p);
printf("%lld\n",f(a,b,p)%p);
}
return 0;
}