题意:求从 1 到 N 中共有多少个数可以表示成 M^K 的形式 , K>1 且 N≤1e18;
分析:首先看 K ,若存在 M 满足 M^K<=N ,则对于所有的 m<=M ,都有 m^K<=N,且由于2^60>1e18,K上限为60,所以我们枚举K,但是如果我们枚举的K不互质的话肯定会存在重复,比如 2^4 和 4^2,所以进一步我们需要枚举K为质数的情况,但是就算这样枚举还是会有重复,比如 9^3 和 27^2,所以这时候需要用到容斥原理:
prime[1] + prime[2] + ... + prime[m] - prime[1]*prime[2] - prime[1]*prime[3] - .... :prime[1]*prime[2] 表示 K 为第一个质数和第二个质数的乘积时候的答案,即若幂次的质因子分解为奇数个时累加贡献,反之减去贡献;
代码:
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
const double eps = 1e-8;
const int N = 61;
typedef long long ll;
ll n;
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
void solve(){
ll ans=0;
int ub=0;
while(1ll<<prime[ub+1]<=n) ub++;
for(int i=1;i<(1<<ub);i++){
ll res=1;
int cnt=0;
for(int j=0;j<ub;j++)
if(i>>j&1){
++cnt;
res*=prime[j];
}
if(cnt&1) ans+=(ll)(pow(n,1.0/res)+eps);
else ans-=(ll)(pow(n,1.0/res)+eps);
}
printf("%lld\n",ans+1);
}
int main()
{
while(~scanf("%lld",&n)){
solve();
}
}