题意
传送门 POJ 2720
题解
欧拉定理:对于和 m m m 互素的 x x x,有
x φ ( m ) ≡ 1 ( m o d m ) x^{\varphi(m)}\equiv 1(mod\ m) xφ(m)≡1(mod m)
拓展欧拉定理:对于 m m m 与 x x x 不一定互质的情况,有
x e m o d m = { x e m o d m e < φ ( m ) x e m o d φ ( m ) + φ ( m ) m o d m o t h e r w i s e x^e\ mod\ m=\begin{cases} x^e\ mod\ m&e<\varphi(m)\\ x^{e\ mod\ \varphi(m)\ +\ \varphi(m)}\ mod\ m&otherwise \end{cases} xe mod m={xe mod mxe mod φ(m) + φ(m) mod me<φ(m)otherwise
对于条件的判断依赖于 e e e 的原值大小,而 e e e 可能为取模后回溯的值,处理比较麻烦。手动取一个大于任意 φ ( m ) \varphi(m) φ(m) 的边界即可,这里取 1 e 7 1e7 1e7,则对于大于此边界的值,递归求解;否则,直接取模。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 101
typedef long long ll;
const int mod = 10000000;
int B, I, N;
int fx[maxn][maxn], rec[maxn][maxn]; // f(x); 最大模值对应的结果, 较小模值可直接向其取模
int mod_table[8]; // 不同数位的模
int phi[maxn]; // 递归深度对应的欧拉函数
// 快速幂, res >= mod 返回 -1
int pow(int n, int e)
{
ll res = 1, x = n;
while (e > 0)
{
if (e & 1)
{
res = res * x;
if (res >= mod)
return -1;
}
x = x * x;
if (x >= mod)
return -1;
e >>= 1;
}
return res;
}
// 快速幂模运算
ll mod_pow(ll n, ll e, ll mod)
{
ll res = 1;
while (e > 0)
{
if (e & 1)
{
res = res * n % mod;
}
n = n * n % mod;
e >>= 1;
}
return res;
}
// 递归求解 f(x) % mod
int dfs(int b, int i, int dep)
{
int mod = phi[dep];
if(fx[b][i] == -1){
return mod_pow(b, dfs(b, i - 1, dep + 1) + mod, mod);
}
else{
return fx[b][i] % mod;
}
}
void output(int n)
{
char format[] = "%00d\n";
format[2] = N + '0';
printf(format, n);
}
void solve()
{
if (rec[B][I] != -1)
{
output(rec[B][I] % mod_table[N]);
return;
}
int res = dfs(B, I, 0);
output((rec[B][I] = res) % mod_table[N]);
}
// 欧拉函数
int euler_phi(int n)
{
int res = n;
for (int i = 2; i * i <= n; i++)
{
if (n % i == 0)
{
res = res / i * (i - 1);
for (; n % i == 0; n /= i)
;
}
}
if (n != 1)
res = res / n * (n - 1);
return res;
}
void init()
{
mod_table[0] = 1;
for (int i = 1; i < 8; i++)
{
mod_table[i] = mod_table[i - 1] * 10;
}
phi[0] = mod;
for (int i = 1; i < maxn; i++)
{
phi[i] = euler_phi(phi[i - 1]);
}
memset(rec, -1, sizeof(rec));
for (int i = 0; i < maxn; i++)
{
rec[i][0] = rec[1][i] = 1;
}
memset(fx, -1, sizeof(fx));
for (int b = 1; b < maxn; b++)
{
fx[b][0] = 1;
for (int i = 1; i < maxn; i++)
{
fx[b][i] = pow(b, fx[b][i - 1]);
if (fx[b][i] == -1)
break;
}
}
}
int main()
{
init();
while (~scanf("%d", &B) && B)
{
scanf("%d%d", &I, &N);
solve();
}
return 0;
}