Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。
这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。
正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。
为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。
这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。
正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。
为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。
Input 本题有多组测试数据,每组包含一个整数N,1<=N<=1000000000000000000(10^18).
Output 对于每组输入,请输出在在1到N之间形式如M^K的数的总数。
每组输出占一行。
Sample Input
10 36 1000000000000000000Sample Output
4 9 1001003332
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
vector<ll> q;
ll prime[maxn];
ll ans, n;
int vis[maxn];
int cnt;
void is_prime()
{
memset(vis, 0, sizeof(vis));
for(ll i = 2; i < maxn; i++)
{
if(vis[i])
continue;
prime[cnt++] = i;
for(ll j = i*i; j < maxn; j += i)
vis[j] = 1;
}
}
// 枚举 素数 的次数, 例如 n = 10, 2次方 的数有 1,2,3,需要把1 减去,因为1 就算一次
// 如果 n^2 m^3 如果 n = t^3, m = t^2, 这样子就会重复算,因此采用容斥原理 ,奇加偶减
// 2^n = n, 这样子次方数是最大,因此数不能超过t
void dfs(int dep,int mul,int num)
{
for(int i = num; i < cnt && prime[i]*mul <= (int)(log(n)/log(2.0)); i++)
{
ll tp = mul*prime[i];
if(dep&1)
ans -= (ll)(pow(n,(double)1/tp)) - 1;
else
ans += (ll)(pow(n,(double)1/tp)) - 1;
dfs(dep+1, tp, i+1);
}
}
int main()
{
while(~scanf("%lld", &n))
{
cnt = 0;
is_prime();
q.clear();
ans = 1;
dfs(0,1,0);
printf("%lld\n",ans);
}
return 0;
}