2204 Eddy's愛好 容斥
阿新 • • 發佈:2018-12-18
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
題解:很明顯要用容斥去做,但1e18最多可以開64次方,64以內的素數有18個,但是2*3*5=30 所以容斥3層即可
1次方是不能算的 所以計算的時候都要減1 但是1可以寫成1的任意次方 所以結果加1
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int N=12; typedef long long ll; ll n,m,a[N]; int prime[70]; int ok[50],len; void init() { prime[1]=1; for(int i=2;i<=64;i++) { if(!prime[i]) { ok[len++]=i; for(int j=i+i;j<=64;j+=i) prime[j]=1; } } } int main() { init(); while(scanf("%lld",&n)!=EOF) { ll ans=0; for(int i=0;i<len;i++) { int tmp=pow(n,1.0/ok[i]); ans+=tmp-1; for(int j=i+1;j<len;j++) { tmp=pow(n,1.0/ok[i]/ok[j]); ans-=tmp-1; for(int k=j+1;k<len;k++) { tmp=pow(n,1.0/ok[i]/ok[j]/ok[k]); ans+=tmp-1; } } } cout<<ans+1<<endl; } return 0; }