CF-1445 C

题意

给定一个 (p (ple 10^{18})), 一个 (q(q le 10^9)), 要找到一个最大的 (x) 满足:

  1. (p \%x = 0)
  2. (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;
}

贴一下官方题解,原理与上述一致。

原文地址:https://www.cnblogs.com/1625--H/p/13956157.html