题意
给定一个 (p (ple 10^{18})), 一个 (q(q le 10^9)), 要找到一个最大的 (x) 满足:
- (p \%x = 0)
- (q \% x eq 0)
分析
直接枚举 (p) 的因数不可取,复杂度为 (O(sqrt p))。需要另辟蹊径。
容易发现,若 (p\%q eq 0) ,那么答案即为 (p)
接下来考虑 (p\%q = 0) 的情况。
考虑到唯一分解的定理对于任意一个大于 1 的数字 n 都有
[n = q_1^{c_1}q_2^{c_2}cdots q_n^{c_n}
]
其中 (q_i) 为 (n) 的质因数,(c_i) 为其指数。
如果一个整数 (n) 不能被 (m) 整除,那么肯定有一个质数 (e),它在 (n) 中的指数小于在 (m) 中的指数。例如 (12 = 2^2*3^1) 与 (8 = 2^3 * 3^0)。
然后我们枚举这个 (e),它必定是 (q) 的一个质因数,所以我们枚举 (q) 的质因子 (e),然后不断的让 (p) 除以 (e),直到 (p\%q eq 0),此时的 (p) 就是满足题目要求的 (x),最后在所有的情况中取一个最大的 (x) 即可。
单组询问复杂度 (O(sqrt q))
int T;
ll p, q;
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}
void solve(ll t){
ll res = 0;
// 枚举 q 的质因数
for(int i = 2; i * i <= t;i++){
if(t % i) continue;
ll now = p; // 尝试不断的用 i 去除 p, 直到 p % q != 0
while(now % q == 0) now /= i;
while(t % i == 0) t /= i;
res = max(res, now);
}
if(t > 1){ // 质因数分解的最后一步
ll now = p;
while(now % q == 0) now /= t;
res = max(res, now);
}
printf("%lld
", res);
}
int main(){
cin >> T;
while(T--){
scanf("%lld%lld", &p, &q);
if(p % q == 0) {
solve(q);
} else {
printf("%lld
", p);
}
}
return 0;
}
贴一下官方题解,原理与上述一致。