Luogu P9118
首先 \(b=1\) 显然直接输出 \(n\)。
剩下的考虑枚举指数,用 set 去重。
枚举指数 \(i\) 至 \(2^i > n\),这样可以做到 \(O(n^{\frac 1k} + n^{\frac 1{k+1}} + n^{\frac 1{k+2}}\dots)\) 的复杂度,虽然我不会算,但是肉眼观察当 \(k=2\) 时只比根号稍微高一点。
容易发现 \(k=3\) 时,即使 \(n=10^{18}\) 也只有大约 \(10^6\) 的计算量,可以考虑先把指数 \(\ge 3\) 的数先算出来,再处理指数为 \(2\) 的。
显然如果不考虑重复的话能表示为 \(a^2,a\in\mathbb N^*\) 的数有 \(\sqrt n\) 个,从已经算出来的数中把平方数删掉即可。
这题有几个坑点,一个是如果要用快速幂要开 int128,还有一个是开根要用 sqrtl,否则会炸精度 WA。
// rp++
#include<bits/stdc++.h>
#define rep(i, s, t) for(int i = s; i <= t; ++i)
#define per(i, s, t) for(int i = s; i >= t; --i)
#define int ll
#define endl '\n'
#define F first
#define S second
typedef long long ll;
typedef __uint128_t u128;
constexpr int N = 1e5 + 5;
using namespace std;
int n, k;
u128 pw(u128 a, int b) {
u128 res = 1;
for(; b; b >>= 1) {
if(b & 1) res *= a;
a *= a;
}
return res;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> k;
if(k == 1) {
cout << n << endl;
return 0;
}
set<uint64_t> st;
for(int i = max(k, 3ll); 1; ++i) {
u128 tmp; int j = 1;
if(i == 2) for(; (tmp = (u128)j * j) <= n; ++j) st.emplace(tmp);
else for(; (tmp = pw(j, i)) <= n; ++j) st.emplace(tmp);
if(j == 2) break;
}
if(k == 2) {
int res = sqrtl(n);
for(auto i : st) {
int r = sqrtl(i);
if(r * r == i) --res;
}
cout << st.size() + res << endl;
}
else cout << st.size() << endl;
return 0;
}

浙公网安备 33010602011771号