zoukankan      html  css  js  c++  java
  • hdu2204Eddy's爱好

    大概题意是要你输出1到n中,可以表示成a^b的数,a,b都是大于0的整数的个数,
    当中b大于1。
    由于1到n中。可以全然开平方的个数就是(n^0.5)的整数部分。
    以此类推能够得到,全然开立方。全然开四次方各种的次数。


    这种话,要枚举的数量太大。有什么办法能够让枚举的数量降低呢?
    有的,因为随意一个大于1的整数都能够表示成两个素数的乘积。
    于是。可以全然开平方的个数包含了可以全然开四次方,
    八次方。十六次方以此类推的个数。
    于是,可以知道,仅仅须要枚举可以全然开素数次方的个数就可以。
    又由于n最大不会超过10^18,由于64位整型号可以表示的最大数
    大概就是9*10^18多,所以不须要特地写个大数。
    又由于这样。所以素数仅仅须要枚举到大小不超过63就可以。由于
    2^63-1就是64位整型的最大值。所以这个n最大,开个63次方的整数部分
    结果肯定为1,为1的话就代表可以1到n中可以全然开这个次方
    的数仅仅有1个,又由于1可以开随意次方,所以,这个数肯定是1啦,
    于是超过63的素数不是必需枚举了,由于仅仅有1可以开这么多次方。

    对于一个数n,从小到大枚举到使n开次方为1就可以,再把前面
    全部开次方的结果都累加,再除去之中反复的部分。终于结果就是
    题意所要求的个数。

    反复的部分是说,可以全然开六次方的肯定也可以全然开二次方和三次方,
    这个能全然开六次方的个数被反复加了一次。所以要减去一次,
    以此类推把全部反复的部分除去就可以。

    另一点,这个题目,有的人用long long读入n的时候,会wa,
    这个的话,是各种编译器的原因,用cin读入就好了,
    至于有的人说缺失精度什么的。仅仅是想多了。

    我的代码例如以下:

    #include<iostream>
    #include<cmath>
    using namespace std;
    int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
    void result(long long x)
    {
    	int i,j,k;
    	long long tmp,ans=1;
    	for(i=0;;i++)
    	{
    		tmp=(long long)(pow(x,1.0/prime[i]));
    		if(tmp<2)
    			break;
    		ans+=tmp-1;
    		for(j=i+1;;j++)
    		{
    			tmp=(long long)(pow(x,1.0/(prime[i]*prime[j])));
    			if(tmp<2)
    				break;
    			ans-=tmp-1;
    			for(k=j+1;;k++)
    			{
    				tmp=(long long)(pow(x,1.0/(prime[i]*prime[j]*prime[k])));
    				if(tmp<2)
    					break;
    				ans+=tmp-1;
    			}
    		}
    	}
    	printf("%lld
    ",ans);
    }
    int main()
    {
    	long long x;
    	while(cin>>x)
    		result(x);
    }


  • 相关阅读:
    [暑假集训Day4T1]羊圈
    [暑假集训Day3T3]平板涂色
    [暑假集训Day3T2]骑士问题
    [暑假集训Day3T1]小木棍
    [暑假集训Day2T3]团建活动
    [暑假集训Day2T2]走廊泼水节
    [暑假集训Day2T1]种树
    [暑假集训Day1T3]新的开始
    [暑假集训Day1T2]北极通讯网络
    [暑假集训Day1T1]黑暗城堡
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6852647.html
Copyright © 2011-2022 走看看