[模拟赛] 签到题(math)

前言:

\(n \leq 1e18\),不会正解,但是 \(O(\sqrt n)\) 过了?

upd:放个大质数就卡掉了。

题面描述:

给定正整数 \(n\)\(k\),请求出最大的正整数 \(a\) 使得 \(a^k | n\)

解题思路:

如果 \(k=1\) 那么答案就是 \(n\)

如果 \(k>2\) 那么可以在 \(O(\sqrt[k]{n})\) 的时间复杂度内做完。

如果 \(k=2\),这种情况会麻烦一点,首先你不能直接枚举,这样是 \(O(\sqrt n)\) 的。但是你首先想到大于 \(\sqrt[3]{n}\) 的质因子个数不会超过两个,所以我们可以把所有小于等于 \(\sqrt[3]{n}\) 的质因子先去掉,剩下的只有可能是一个或者两个质因子组成的数。

再又观察到一个质因子,只有出现超过两次才会产生贡献,所以直接判断剩下的数是不是平方数即可。

当然在 \(k>2\) 的情况也可以按照上述方法做,这样就不用害怕爆 long long 了。

代码实现:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int qpow(int a, int b){
    int res = 1;
    while(b){
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}
int n, k, ans = 1;
vector<pair<int, int> > v;
signed main(){
    freopen("math.in", "r", stdin);
    freopen("math.out", "w", stdout);
    cin >> n >> k;
    if(k == 1) return cout << n << endl, 0;
    for(int i = 2; i * i * i <= n; i++){
        if(n % i == 0){
            int cnt = 0;
            while(n % i == 0) n /= i, cnt++;
            v.push_back({i, cnt});
        }
    }
    for(auto [i, cnt] : v) ans = ans * qpow(i, cnt / k);
    if((int)sqrtl(n) * (int)sqrtl(n) == n) ans *= (int)sqrtl(n);
    cout << ans << endl;
    return 0;
}
posted @ 2025-11-20 16:08  _huangweiliang  阅读(2)  评论(1)    收藏  举报