HDU2204 Eddy's爱好(容斥原理)

题目问[1,n]有几个数是$m^k (k>1)$形式。

如果这样考虑,m已知k未知,对于每一个m统计其k的数量即$\lfloor log_mn \rfloor$个,再容斥,然而m太多了,完全不可行。

而k远远比m还少,应该反过来考虑,m未知k已知,对于每一个k统计其m的数量,即$\lfloor \sqrt[k]n \rfloor$

由于$n \leqslant 10^{18}$,而$2^{60} > 10^{18}$,所以k的范围就是小于60的整数。

然而60用容斥$2^{60}$还是不可行,而$m^{a \times b}$,已知就被$m^a$和$m^b$计数过了,所以对于所有60以内的合数完全可以在一开始就除去,即只考虑60以内的质数。

而60以内的质数只有17个,那么就OK了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 using namespace std;
 5 int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61};
 6 int main(){
 7     long long n;
 8     while(~scanf("%lld",&n)){
 9         int pn=0;
10         while((1LL<<prime[pn+1])<=n) ++pn;
11         long long res=0;
12         for(int i=1; i<(1<<pn); ++i){
13             long long tmp=1; int cnt=0;
14             for(int j=0; j<pn; ++j){
15                 if(((i>>j)&1)==0) continue;
16                 tmp*=prime[j]; ++cnt;
17             }
18             if(cnt&1) res+=(long long)(pow(n,1.0/tmp)+1e-8);
19             else res-=(long long)(pow(n,1.0/tmp)+1e-8);
20         }
21         printf("%lld\n",res+1);
22     }
23     return 0;
24 }

 

posted @ 2016-02-05 09:08  WABoss  阅读(258)  评论(0编辑  收藏  举报