題意:
求最小的x,滿足log*(x)>=b
思路:
容易發現答案就是
首先不要犯一個錯誤:
歐拉函數有:
如果原數爲,那麼解決B就是解決原數的一個子問題,那麼可以利用遞歸來解決這個問題。
遞歸的終點顯然是深度爲B,但是這樣會超時,繼續觀察一下,發現在遞歸的時候,模數差不多是歐拉函數套歐拉函數,最後模數很快就會變成1,然後在遞歸下去全部模1變爲0就沒有意義在遞歸下去了,就需要及時返回。
參考代碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn =1e6+5;
bool vis[maxn];
ll phi[maxn];
ll p[maxn];
void work_euler(int n)//On
{
memset(vis,1,sizeof(vis));
vis[0]=vis[1]=false;
phi[1]=1;
for (int i=2;i<=n;i++)
{
if(vis[i]) p[++p[0]]=i,phi[i]=i-1;
for(int j=1;j<=p[0]&&p[j]*i<=n;j++)
{
vis[p[j]*i]=false;
if (i%p[j]) phi[p[j]*i]=phi[p[j]]*phi[i];
else{phi[p[j]*i]=p[j]*phi[i];break;}
}
}
}
ll q_pow(ll a,ll n,ll m){
ll res=1;
while(n){
if(n&1)res=res*a%m;
a=a*a%m;
n>>=1;
}
return res;
}
ll a,b;
ll solve(ll k,ll m){
if(k>b||m==1)return 1;
ll zs=solve(k+1,phi[m]);
double cmp=log(m)/log(a);//換底公式loga(m)
if(zs-cmp>=0)return q_pow(a,zs,m)+m;
else return q_pow(a,zs,m);
}
int main(){
work_euler(maxn-5);
int T;
scanf("%d",&T);
while(T--){
ll m;
scanf("%lld%lld%lld",&a,&b,&m);
ll ans=1;
if(b==0)printf("%lld\n",ans%m);//簡單情況直接特判
else if(b==1)printf("%lld\n",a%m);
else if(b==2)printf("%lld\n",q_pow(a,a,m));
else printf("%lld\n",solve(1,m)%m);
}
return 0;
}