[模拟赛] 签到题(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;
}

浙公网安备 33010602011771号