HDU - 2204 容斥原理

Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。
这些特殊数是这样的:这些数都能表示成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
1000000000000000000
Sample 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;
}


猜你喜欢

转载自blog.csdn.net/qq_38295645/article/details/80357912