面白かった
問題概要
正の整数 が与えられる。
の約数であって、 の倍数ではないような整数の最大値を求めよ。
(というデータセットが 個与えられる)
制約
考えたこと
の約数をすべて列挙したのでは間に合わない。とりあえず 自身が で割り切れないならば、 が答えになることはわかる。
が で割り切れるとき、次のことがわかる。 を素因数分解して
としたとき、 の に対する指数がそれぞれ 以上となる。
よって、 の約数であって の倍数でないような、なるべく大きい整数を作るためには、
- の に対する指数を まで下げたもの
- の に対する指数を まで下げたもの
- ...
- の に対する指数を まで下げたもの
を比較して、そのうち最大のものを求めれば OK。計算量は 。
#include <bits/stdc++.h> #include <sys/time.h> using namespace std; template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; } template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; } vector<pair<long long, long long> > prime_factorize(long long n) { vector<pair<long long, long long> > res; for (long long p = 2; p * p <= n; ++p) { if (n % p != 0) continue; int num = 0; while (n % p == 0) { ++num; n /= p; } res.push_back(make_pair(p, num)); } if (n != 1) res.push_back(make_pair(n, 1)); return res; } long long solve(long long P, long long Q) { if (P % Q != 0) return P; auto pf = prime_factorize(Q); long long res = 0; for (auto it : pf) { long long P2 = P; long long p = it.first, e = it.second; while (P2 % p == 0) P2 /= p; for (long long j = 0; j < e-1; ++j) P2 *= p; chmax(res, P2); } return res; } int main() { int T; cin >> T; while (T--) { long long p, q; cin >> p >> q; cout << solve(p, q) << endl; } }