【HDU 2204】Eddy's爱好(容斥原理)

Eddy's爱好

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2885    Accepted Submission(s): 1408


Problem Description
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

对于这道题,我们仔细思考就会发现,K只有在质数情况下才有效(如果是非质数,根据容斥原理就会被消掉),因此我们预处理前17个质数(小于60的),然后直接进行容斥,对于一个数n,那么假设质数为k,那么此时M^k的个数为pow(n,1.0/k)-1(先不考虑1),然后由于2*3*5*7>60,因此最多也就是三重循环,三个集合进行容斥再加上1,就是答案。

#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
ll pre[17] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59 };
ll n;
ll work(ll k)
{
	return pow(n,1.0/k)-1;//指数为k时的个数(1除外) 
}
int main()
{
	while(cin>>n)
	{
		ll ans1=0;
		ll ans2=0;
		ll ans3=0;
		for(int i=0;i<17;i++)
		{
			ans1+=work(pre[i]);
		}
		for(int i=0;i<17;i++)
		{
			for(int j=i+1;j<17;j++)
			{
				ans2+=work(pre[i]*pre[j]);
			}
		}
		for(int i=0;i<17;i++)
		{
			for(int j=i+1;j<17;j++)
			{
				for(int k=j+1;k<17;k++)
				{
					ans3+=work(pre[i]*pre[j]*pre[k]);
				}
			}
		}
		cout<<ans1+ans3-ans2+1<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/duanghaha/article/details/81046037
今日推荐