#include #include #include using namespace std; using u64 = unsigned long long; u64 uz = time(NULL); u64 xorshift64() { uz ^= uz << 13; uz ^= uz >> 7; uz ^= uz << 17; return uz; } // floor( log2(x) ) int log2_64(u64 x) { if(x == 0) { return 0; } return 63 - __builtin_clzll(x); } // 戻り値が 0 ならオーバーフローなどで失敗したことを表すことにする u64 mypow(u64 a, int b) { if(log2_64(a) * b > 64) { return 0; } u64 res = 1ULL; while(b) { if(b & 1) { res *= a; } a *= a; b >>= 1; } return res; } u64 mod_mul(u64 a, u64 b, u64 m) { __uint128_t a128 = a; a128 *= b; a128 %= m; return a128; } u64 mod_pow(u64 x, u64 k, u64 m) { if(k == 0) { return 1; } if(k & 1) { return mod_mul(x, mod_pow(x, k-1, m), m); } return mod_pow(mod_mul(x, x, m), k>>1, m); } bool is_probable_prime(u64 n) { constexpr int k = 30; if(n < 2) { return false; } for(u64&& p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31}) { if(n < p * p) { return true; } if(n % p == 0) { return false; } } u64 s = 0, d = n-1; while(!(d & 1)) { ++s, d>>=1; } for(int loop=0; loop 1) { u64 md = (lo + hi) / 2; u64 pw = mypow(md, a); if(pw == 0 || pw > pa) { hi = md; } else { lo = md; } } return lo; } bool f(u64 n) { if(n == 2) { return false; } if(n % 2 == 0) { return true; } for(u64 b=2; b