Mr. Panda and Kakin
给定n,cn, cn,c,要我们找到nnn是两个相邻质数的乘积,要我们找到xxx,满足x230+3≡c(modn)x ^{2 ^{30} + 3} \equiv c \pmod nx230+3≡c(modn),1010≤n≤1018,0<c<n10 ^{10} \leq n \leq 10 ^ {18}, 0 < c < n1010≤n≤1018,0<c<n,
考虑得到230+32 ^{30} + 3230+3模ϕ(n)\phi(n)ϕ(n)下的逆元,为inv=(230+3)ϕ(n)−1inv = (2 ^{30} + 3) ^{\phi(n) - 1}inv=(230+3)ϕ(n)−1,则有cinv≡x(230+3)inv≡x(modn)c ^{inv} \equiv x ^{(2^{30} + 3)inv} \equiv x \pmod{n}cinv≡x(230+3)inv≡x(modn),使用O(1)O(1)O(1)快速乘即可。
#include <bits/stdc++.h>using namespace std;long long n, c, phi, inv;inline long long mul(long long x, long long y, long long mod) {return (x * y - (long long)((long double)x / mod * y) * mod + mod) % mod;
}long long exgcd(long long a, long long b, long long & x, long long & y) {if(!b) {x = 1, y = 0;sreturn a;}long long gcd = exgcd(b, a % b, x, y);long long temp = x;x = y;y = temp - a / b * y;return gcd;
}long long quick_pow(long long a, long long n, long long mod) {long long ans = 1;while (n) {if (n & 1) {ans = mul(ans, a, mod);}a = mul(a, a, mod);n >>= 1;}return ans;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);int T, cas = 0;scanf("%d", &T);while (T--) {scanf("%lld %lld", &n, &c);long long p = sqrt(n), q;while (true) {if (n % p == 0) {break;}p--;}q = n / p;phi = (p - 1) * (q - 1);exgcd((1ll << 30) + 3, phi, inv, p);inv = ((inv % phi) + phi) % phi;printf("Case %d: %lld\n", ++cas, quick_pow(c, inv, n));}return 0;
}