题目:
分析:一道欧拉降幂的题,关键是要知道多次(最多25次)欧拉降幂后最后取模会变为1,也就是指数会变为0,剩下的直接求。
ac code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+1;
int phi[maxn],prime[maxn],isprime[maxn];
int tot;
struct Node{
ll ans;
bool flag;///用于判断a^b%p中是否满足b>=phi[p];
Node(ll ans=0,bool flag=0):ans(ans),flag(flag){}
};
Node Pow(ll a,ll b,ll mod)
{
ll ans=1;
bool flag=1;
while(b){
if(b&1){
ans*=a;
if(ans>=mod){
flag=0;
ans%=mod;
}
}
b>>=1;
if(b){
if(a>=mod) flag=0;
a%=mod;
a*=a;
if(a>=mod) flag=0;
a%=mod;
}
}
return Node(ans,flag);
}
void eluer_table()
{
phi[1] = 1;
isprime[1] = 1;
for(int i = 2; i < maxn; i ++) {
if(!isprime[i]) {
prime[++ tot] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= tot && i * prime[j] < maxn; j ++) {
isprime[i * prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
Node solve(ll a,ll b,ll k,ll p)
{
if(p==1) return Node(0,0);
if(k==0) return Node(a%p,a<p);
ll ph=phi[p];
Node tmp=solve(b,b,k-1,ph);
if(__gcd(a,p)==1) return Pow(a,tmp.ans,p);
if(!tmp.flag)
tmp.ans+=ph;
return Pow(a,tmp.ans,p);
}
int main()
{
//clock_t be=clock();
eluer_table();
//clock_t en=clock();
//printf("%.2f\n",(en-be)/1000.0);
ll a,b,k,p;
int t;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld%lld",&a,&b,&k,&p);
ll ans=solve(a,b,k,p).ans;
printf("%lld\n",ans);
}
return 0;
}