Mr. Panda and Kakin
给定 n , c n, c n,c,要我们找到 n n n是两个相邻质数的乘积,要我们找到 x x x,满足 x 2 30 + 3 ≡ c ( m o d n ) x ^{2 ^{30} + 3} \equiv c \pmod n x230+3≡c(modn), 1 0 10 ≤ n ≤ 1 0 18 , 0 < c < n 10 ^{10} \leq n \leq 10 ^ {18}, 0 < c < n 1010≤n≤1018,0<c<n,
考虑得到 2 30 + 3 2 ^{30} + 3 230+3模 ϕ ( n ) \phi(n) ϕ(n)下的逆元,为 i n v = ( 2 30 + 3 ) ϕ ( n ) − 1 inv = (2 ^{30} + 3) ^{\phi(n) - 1} inv=(230+3)ϕ(n)−1,则有 c i n v ≡ x ( 2 30 + 3 ) i n v ≡ x ( m o d n ) 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;s
return 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;
}