代码附有详细解释,求教大佬!
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, k, mn, ans, a[65], lim[65] = {0, 0, 1000000000, 1000000, 31622, 3981, 1000, 372, 177, 100, 63, 43, 31, 24, 19, 15, 13, 11, 10, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, range[65], num[65]; //lim[i]表示在a^i在long long范围内的最大取值a,防止溢出
int calc(int b, int p) { // 求[1,b]之间有多少个形如a^p的数
int l = 0, r = 1e9;
while(l <= r) {
int mid = l+r >> 1;
if(mid > lim[p]) {r = mid-1; continue;}
int x = pow(mid, p);
if(x > b) r = mid-1;
else l = mid+1;
}
return r;
}
signed main () {
scanf("%lld%lld", &n, &k);
for(int i = 1;i <= 64;++i) num[i] = i;
if(k == 1) printf("%lld", n), exit(0);
int mx = log2(n);
for(int i = 1;i < k;++i) num[i] = 0;
for(int i = k;i <= 64;++i)
for(int j = 2*i;j <= 64;j += i)
num[j] = 0;
for(int i = 1;i <= 64;++i)
if(num[i]) a[i] = 1; // a数组表示需要筛查的次方数(a数组元素两两互质)
for(int i = 2;i <= mx;++i) {
if(!a[i]) continue;
range[i] = calc(n, i);
}
for(int i = k;i <= mx;++i) {
if(a[i] == 0) continue;
ans += range[i];
for(int j = k;j < i;++j) {
if(!a[j]) continue;
ans -= calc(range[i], j) - 1; // 排除之前算过的数(例如4^3,在i=2时计算了一次,i=3时又算了一次,重复了。减1意思是把1去掉,因为1每一遍都有)
}
--ans; //去1
}
printf("%lld\n", ans+1); // 前面我们都把1排除在外了,最后应该给答案+1
return 0;
}