HDU-2204-Eddy's愛好-容斥求n之內有多少個數形如M^K

HDU-2204-Eddy's愛好-容斥求n之內有多少個數形如M^K


【Problem Description】

php

【Solution】

對於一個指數\(k\),找到一個最大的\(m\)使得\(m^k\le n\),則\(k\)這個指數對答案的貢獻爲\(m\),由於對於\(i\in[1,m]\)中的數\(i^k\)必定小於等於\(n\)。而\(m=n^{\frac{1}{k}}\)。由惟一分解定理可知,\(k\)必定能表示爲一些素數的乘積。因此只須要考慮\(64\)之內的素數便可。可是會出現重複的值,例如\(8^2=4^3=2^{2\times 3}\),因此須要用容斥去重便可。ios


【Code】

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f
#define maxn 65
int prime[maxn],cnt=0;
bool vis[maxn]={1,1};
void Euler(){ //歐拉篩素數
    for(int i=2;i<maxn;i++){
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<maxn;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
int n,ans=0;
int fpow(int a,int b){ //快速冪
    int ans=1;
    while(b){
        if(b&1) ans*=a;
        a*=a;
        b>>=1;
    }
    return ans;
}
void dfs(int pos,int num,int val){ //容斥
    if(val>64) return ; //最大值不超過64
    int tmp=pow(n,1.0/val)+0.1; //求最大的m
    if(fpow(tmp,val)>n) tmp--;tmp--; //精度判斷
    if(num) if(num&1) ans+=tmp;
    else ans-=tmp;
    for(int i=pos+1;i<=cnt;i++){
        dfs(i,num+1,val*prime[i]);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);Euler();
    while(cin>>n){
        ans=1;//1必定知足條件
        dfs(0,0,1);
        cout<<ans<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索