首先介绍一下欧拉函数和扩展欧拉定理(phi指的是欧拉定理)
a^b = a^(b%phi(p)) gcd(a,p) == 1 (mod p)
a^b gcd(a,p) != 1 b < phi(p) (mod p)
a^(b%phi(p)+phi(p)) gcd(a,p) != 1 b >= phi(p) (mod p)
本题用到的就是三式
cal函数为求出这个式子对p取mod的结果
开始时设底数为2,指数为2的2次方的2次方…… ,cal(原式)的结果为w,应用公式,cal(原式) = 2 ^ (剩余数%phi(p)+ p)。
所以结果为2的(剩余数%phi(p)+ p),可以用快速幂求出,而指数部分的(剩余数%phi(p))仍可以按上述方法求解,于是递归求解即可
注意:当p == 1时,对1取mod应返回0,即为终止条件,输出即可。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll ksm(ll x, ll y,ll mode)
{
ll ans = 1;
while(y)
{
if(y % 2 == 1)
{
ans = ans * x % mode;
}
x = x * x %mode ;
y = y/2;
}
return ans;
}
ll phi(ll x)
{
ll ans = x;
for(ll i = 2 ; i * i <= x ;i++)
{
if(x % i == 0)
{
ans = ans / i * (i - 1);
while(x % i == 0)
{
x /= i;
}
}
}
if(x != 1)
{
ans = ans / x * (x - 1);
}
return ans;
}
ll cal(ll x)
{
if(x == 1)
{
return 0;
}
ll t = phi(x);
return ksm(2,cal(t) + t, x);
}
int main()
{
int t;
scanf("%d", &t);
ll p;
for(int i = 1;i <= t;i++)
{
scanf("%lld", &p);
printf("%lld\n",cal(p));
}
return 0;
}
/* a^b = a^(b%phi(p)) gcd(a,p) == 1 (mod p)
a^b gcd(a,p) != 1 b < phi(p) (mod p)
a^(b%phi(p)+phi(p)) a,p 可以不互质 b >= phi(p) (mod p)
*/