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; }