形如以下式子的东西叫做幂塔:
a
a
a
a
.
.
.
a^{a^{a^{a^{...}}}}
aaaa...
题目
给定
a
,
n
,
m
a,n,m
a,n,m,计算
a
a
a的
n
n
n层幂塔对
m
m
m取模后的结果。
(
1
<
=
a
,
n
,
m
<
=
1
e
6
1<= a,n,m<=1e6
1<=a,n,m<=1e6)
解法
欧拉降幂公式
运用欧拉降幂递归求解即可。
具体过程:
定义的递归函数形式: f ( a , n , m ) f(a, n, m) f(a,n,m),表示 a a a的 n n n层幂塔对 m m m取模后的结果。
- 首先是对边界情况的判断(递归结束条件)
1、当 m = 1 m=1 m=1时, f ( a , n , m ) = 0 f(a,n,m)=0 f(a,n,m)=0.
2、当 n < = 1 n<=1 n<=1时, f ( a , n , m ) = p o w ( a , n , m ) f(a,n,m)=pow(a,n,m) f(a,n,m)=pow(a,n,m). - 其他情况(欧拉降幂公式的
3
3
3种情况)
1、当 g c d ( a , m ) = 1 gcd(a,m)=1 gcd(a,m)=1时, f ( a , n , m ) = p o w ( a , f ( a , n − 1 , φ ( m ) ) , m ) f(a,n,m)=pow(a,f(a,n-1,\varphi(m)),m) f(a,n,m)=pow(a,f(a,n−1,φ(m)),m).
2、当 g c d ( a , m ) ≠ 1 gcd(a,m)\neq 1 gcd(a,m)=1 且 a a a的 n − 1 n-1 n−1层幂塔 ≥ φ ( m ) \ge \varphi(m) ≥φ(m)时, f ( a , n , m ) = p o w ( a , f ( a , n − 1 , φ ( m ) ) + φ ( m ) , m ) f(a,n,m)=pow(a,f(a,n-1,\varphi(m))+\varphi(m),m) f(a,n,m)=pow(a,f(a,n−1,φ(m))+φ(m),m).
3、当 g c d ( a , m ) ≠ 1 gcd(a,m)\neq 1 gcd(a,m)=1 且 a a a的 n − 1 n-1 n−1层幂塔 < φ ( m ) < \varphi(m) <φ(m)时, f ( a , n , m ) = p o w ( a , f ( a , n − 1 , φ ( m ) ) , m ) f(a,n,m)=pow(a,f(a,n-1,\varphi(m)),m) f(a,n,m)=pow(a,f(a,n−1,φ(m)),m).
Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
#define INF 0x3f3f3f3f
#define endl '\n'
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int qmi(int a, int b, int mod)
{
int res = 1 % mod;
while(b) { if(b & 1) res = (LL)res * a % mod; a = (LL)a * a % mod; b >>= 1; }
return res;
}
int get_phi(int x)
{
int res = x;
for(int i = 2; i <= x / i; i ++)
if(x % i == 0)
{
res = res / i * (i - 1);
while(x % i == 0) x /= i;
}
if(x > 1) res = res / x * (x - 1);
return res;
}
//判断n层幂塔a是否>=phi
bool check(int a, int n, int phi)
{
if(n == 0) return phi <= 1; //0层幂塔是1
if(a >= phi) return true; //底数a>=phi,那么它的幂塔一定>=phi
return check(a, n - 1, log(phi) / log(a));//取对数,消去一层,继续判断
}
//计算n层幂塔: a^a^a^a..^a (mod m)
//其中共有n个a
int f(int a, int n, int m)
{
if(m == 1) return 0; //对1取模,恒为0
if(n <= 1) return qmi(a, n, m);
int phi = get_phi(m);
//互质
if(__gcd(a, m) == 1) return qmi(a, f(a, n - 1, phi), m);
//不互质
if(check(a, n - 1, phi)) return qmi(a, f(a, n - 1, phi) + phi, m);//a的指数>=phi
return qmi(a, f(a, n - 1, phi), m); //a的指数<phi, 所以改成对phi取模对答案无影响
}
int main()
{
#ifdef LOCAL
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
int t; cin >> t;
while (t --)
{
int a, n, m;
cin >> a >> n >> m;
cout << f(a, n, m) << endl;
}
return 0;
}