大数素幂分解
using i128 = __int128_t;const int mod = 1000000007;
i64 fpow(i64 a, i64 b, i64 mod) { i64 ans = 1; i64 base = a; while (b) { if (b & 1) ans = (i128)ans * base % mod; b >>= 1; base = (i128)base * base % mod; } return ans;}
bool Miller_Rabbin(i64 a, i64 n) { i64 r = 0, d = n - 1; while (d % 2 == 0) { d >>= 1; r++; }
i64 x = fpow(a, d, n);
if (x == 1) return true; for (int i = 0; i < r; i++) { if (x == n - 1) return true; x = (i128)x * x % n; }
return false;}
bool isprime(i64 n) { if (n == 2) return true; if (n < 2 || n % 2 == 0) return false; vector<i64> prime = {2, 3, 5, 7, 9, 233, 331}; for (auto t : prime) { if (n == t) return true; if (!Miller_Rabbin(t, n)) return false; } return true;}
i64 gcd(i64 a, i64 b) { return b == 0 ? a : gcd(b, a % b);}
i64 aabs(i64 w) { return w > 0 ? w : -w;}
i64 Pollard_Rho(i64 n) {
i64 c = 1ll * rand() % (n - 1) + 1; auto f = [&](i64 x) -> i64 { return ((i128)x * x + c) % n; }; i64 l = 0, r = 0, cur = 1;
for (i64 i = 1; ; i <<= 1, l = r, cur = 1) { for (i64 j = 1; j <= i; j++) { r = f(r); cur = (i128)cur * aabs(r - l) % n; if (j % 128 == 0) { i64 d = gcd(cur, n); if (d > 1) return d; } } i64 d = gcd(cur, n); if (d > 1) return d; }}
set<i64> w;
void divide(i64 n) { if (n == 1) return; if (isprime(n)) { w.insert(n); return; } i64 p = n; while (p >= n) { p = Pollard_Rho(n); } while (n % p == 0) { n /= p; } divide(n); divide(p);}
// divide(n) 后// w 中会存储所有n的质因子,然后可以再 log 计算出每个质因子的指数