题目链接:https://nanti.jisuanke.com/t/41299
题目大意
已知函数
形式如下:
现在给出
,要找到最小的正整数
,使得
。由于
可能很大,所以需要取模
。
题目分析
多造几组
去算
,可以发现这个问题就是求:
因为暴力求这个数的过程量会非常大,所以需要对过程量取模。但是过程量是指数,我们不能直接对其取模,这里就需要用上欧拉降幂。
知道了这些就里答案很接近了,我们可以每次都把问题递归分解为求利用欧拉降幂解指数部分的值,回归时再计算层指数运算的结果。
要注意:除了分解了 次可以返回之外,欧拉函数迭代到1也可以提前返回,可以减少大量不必要的运算。
黑历史记录:
- 没有想到模数的欧拉函数迭代到1可以提前返回的情况,因为任何正整数取模1都等于0,所以没必要再继续运算。
- 没有考虑到欧拉函数迭代到1是返回值为0时的处理1。
代码如下
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int T, a, b ,m;
int phi[maxn];
ll prime[maxn];
bool vis[maxn];
//快速幂
ll quick_pow(ll x, ll n, ll Mod) {
ll res = 1;
while (n) {
if (n & 1) res = (res * x) % Mod;
x = (x * x) % Mod;
n >>= 1;
}
return res;
}
//线性筛筛求欧拉函数
void getphi(int n) {
int i, j, tot = 0;
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!vis[i]) {
prime[++tot] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= tot && i * prime[j] <= n; j++) {
vis[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] * (prime[j] - 1);
}
}
}
}
int dfs(int a, int b, int m) {
//欧拉函数迭代到1
if (m == 1) return 0;
//已经迭代到最后一次了
if (b == 0) return 1;
int x = dfs(a, b - 1, phi[m]);
//x为0是欧拉函数迭代到1返回的
if (x < phi[m] && x) return quick_pow(a, x, m);
else return quick_pow(a, x + phi[m], m);
}
int main()
{
getphi(maxn-10);
scanf("%d", &T);
while (T--) {
scanf("%d %d %d", &a, &b, &m);
printf("%d\n", dfs(a, b, m));
}
return 0;
}