1. 程式人生 > >hdu2204Eddy's愛好

hdu2204Eddy's愛好

一個 hdu ace 表示 缺失 spa 最大數 void 代碼

大概題意是要你輸出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\n",ans);
}
int main()
{
	long long x;
	while(cin>>x)
		result(x);
}


hdu2204Eddy&#39;s愛好