手写二分sqrt,枚举的i是指数,j是底数set判重
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
ll n, ans, cnt; int k;
bool flag;
set < lll > s;
lll fpow(lll x, lll y) {
if (y == 0) return 1;
if (y == 1) return x;
if (y & 1) return x * fpow(x, y - 1);
else return fpow(x * x, y / 2);
}
lll sqt(lll n) {
lll lo = 0, hi = n;
while(lo < hi) {
lll mid = lo + hi + 1 >> 1;
if(mid * mid <= n) {
lo = mid;
} else {
hi = mid - 1;
}
}
return lo * lo == n ? 1 : -1;
}
int main() {
cin >> n >> k;
int p = log2(n) + 1;
if (k == 2) { flag = true, cnt = sqrt(n); k++; }
for (int i = k; i <= p; i++) {
ll q = pow(n, 1.0 / i) + 2;
for (ll j = 1; j <= q; j++) {
lll po = fpow((lll)j, (lll)i);
if (po <= n && s.count(po) == 0) {
if (flag && sqt(po) != -1) continue;
ans++, s.insert(po);
}
if (po > n) break;
}
}
cout << ans + cnt;
return 0;
}