long long dfs(long long base, long long p)
{
if (p == 1)
return 0;
long long phip = phi(p);
long long y = power(base, dfs(base, phip) + phip, p);
return y;
}
下面开始对本题的正式解法描述。
法一:首先考虑 au≡u(modm) 的形式。如果假设 u 有 ak 形式,则带入可得 aak≡ak(modm)。如果这个 u 充分大(即大于 φ(m)),则根据扩展欧拉定理的指数条件有 ak≡k(modφ(m)),而这个式子与原式形式完全相同且模数减小,因而可以考虑一路递归下去,如此进行到 m=1。这时考虑边界条件,不妨设此时的 u 仍然具有 ak 形式,而这显然成立(模 1 意义下什么值都是 0)。因而,我们可以假定 u 就是 ∞a。
由于 ∞a 对于不同的模数就有不同的值,回到原式考虑这个 u 需要满足什么条件。显然由最基本的条件,a∞a=∞a≡u(modm)。此外,由于它在指数上,因而由 au≡∞a=a∞a(modm) 可得 u≡∞a(modφ(m))。注意这里的 u 要充分大。因而可以得到如下的同余方程:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll mul(ll a, ll b, ll p) {
ll r = a * b - (ll)((long double)a / p * b + 0.5) * p;
return r < 0 ? r + p : r;
}
ll fpow(ll a, ll b, ll p, ll x = 1) {
for (; b; b >>= 1, a = mul(a, a, p))
if (b & 1) x = mul(x, a, p);
return x;
}
int phi(int x) {
int p = x;
for (int i = 2; i * i <= x; i++) {
if (x % i) continue;
p -= p / i;
while (x % i == 0) x /= i;
}
if (x > 1) p -= p / x;
return p;
}
int A;
ll f(ll x) {
if (x == 1) return 1;
ll p = phi(x), lcm = p * x / __gcd(p, x);
return fpow(A, f(p), lcm) + lcm;
}
void Solve() {
int x;
scanf("%d%d", &A, &x);
ll w = f(x), d = (ll)x * phi(x) / __gcd(x, phi(x));
printf("%lld\n", w >= 1e18 ? w % d : w);
}
int main() {
int t = 1;
scanf("%d", &t);
while (t--) Solve();
return 0;
}
法二:首先不难注意到当 gcd(a,m)=1 时,aφ(m)≡1(modm)。如果 φ(m)∣u 且 u≡1(modm) 有解的时候这样的 u 就是合法的。可惜这个同余方程组不一定有解。考虑让上述方程有解,即考虑一个一般情况,即 u 仍然是充分大(大于 φ(m))时,有 au≡ac(modm),其中 c 为一常数且 c∈[φ(m),2φ(m))。则考虑指数和底数条件有:
uu≡ac(modm)≡c(modφ(m))
消去 u 将同余方程组转化为丢番图方程,观察对 c 的约束,有:
ac+k1m=c+k2φ(m)
即 ac−c=k1m+k2φ(m),右侧必为 g=gcd(m,φ(m)) 的倍数。由于 k1,k2 的任意性,右侧可以组合出一切 g 的倍数,因而有 ac≡c(modg),就可以开始递归计算上述方程 c 的解。对于每一轮递归,可以考虑暴力回代解出相应的 u。