hdu 2204 Eddy s愛好(容斥原理)

2021-06-18 03:34:29 字數 1167 閱讀 6385

題意:給你乙個正整數n,確定在1到n之間有多少個可以表示成m^k(k>1)的數。

本題有多組測試資料,每組包含乙個整數n,1<=n<=1000000000000000000(10^18).

解析:

如果 a^xi>=1)必然存在,即有a個數滿足條件其x次冪

把n作為double型數,對其開k次方(我們不難發現,k<61,對於題目要求的n的最大值開61次方就小於2了)得m,則不大m的正整數的k次方就都是要求的整數。如果我們把k從2到60迴圈並把(int)m都加起來,這個和是不是就是要求的答案呢?很明顯不是,如2的4次方和4的平方都是16、2的6次方和4的平方都等於64,這樣以來這個和就可能大於要求的答案了。所以k不能這樣迴圈。我們這樣想:既然2的4次方和4的平方都是16、2的6次方和4的平方都等於64,那麼我們何不只計4的2次方和4的3次方不計2的4次方和2的6次方呢!即我們只需計乙個數的素數次方,這樣我們只用把60以內素數計下來進行計算就會去掉了不少的重複。

是不是這樣算出的結果t就是答案呢?還不是。這一點就不太好想了,讓我費好長時間也找不出反例,還是同學提示才算找到了。比如64(2的2*3次方)既是4的3次方又是8的平方。這一類屬於m的k*p次方型(其中k和p為素數),這樣以來t的值還比答案大,我們就得去掉這一部分。我們將60以內的素數兩兩相乘取60以內的積的集合,再對n開方並去掉這部分的重複,這樣得到t的就去掉了m的k*p次方型的數重複計算。

看起來沒有什麼問題了,可是用上面的測試例項一測還是不對。這又是**出錯了。經過以上種種出錯,這次就不難想出原因了。對於m的k*p*g型的數(k、p、g都是素數),它既是(m^k)^(p*g),又是(m^p)^(k*g),同時又是(m^g)^(k*p),這樣我們的上一部操作又多去掉了一些值。這裡我們把其加上就是了。對於這一型別的數在10^18之內只可能有三個:2的2*3*5次方、2的2*3*7次方以及3的2*3*5次方。如果n包括這幾個數,再加上包括的個數算出的t就是最終答案了。

#include#include#include#includeusing namespace std;

typedef __int64 ll;

ll n,a[20]=;

ll res;

void dfs(int s,ll lcm,int bit)

{ ll m;

m=ll(pow(n,1.0/(lcm)));

while(pow(m+1,0.0+lcm)

hdu 2204 Eddy s愛好 容斥

根據指數的質數分解進行容斥 比如 k a 3 且 k b 5,那麼 k c 15 所以 a 的可選個數 加 b的可選個數減去c的可減個數就是總的個數了因為 a 3和b 5有重複的 include include include include include include define ll lo...

HDU 2204 Eddy s愛好 容斥

ignatius 喜歡收集蝴蝶標本和郵票,但是eddy的愛好很特別,他對數字比較感興趣,他曾經一度沉迷於素數,而現在他對於一些新的特殊數比較有興趣。這些特殊數是這樣的 這些數都能表示成m k,m和k是正整數且k 1。正當他再度沉迷的時候,他發現不知道什麼時候才能知道這樣的數字的數量,因此他又求助於你...

HDU 2204 Eddy s愛好 容斥

input 本題有多組測試資料,每組包含乙個整數n,1 n 1000000000000000000 10 18 output 對於每組輸入,請輸出在在1到n之間形式如m k的數的總數。每組輸出佔一行。sample input 10 361000000000000000000sample output...