hdu2204 Eddy's爱好 打表+容斥原理

Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。
这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。
正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。
为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。

打表+容斥原理

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 using namespace std;
 6 typedef long long ll;
 7 const int pnum=36;
 8 const double eps=1e-8;
 9 
10 int num[40]={0,
11     2,3,5,6,7,
12     10,11,13,14,15,
13     17,19,21,22,23,
14     26,29,30,31,33,
15     34,35,37,38,39,
16     41,42,43,46,47,
17     51,53,55,57,58,
18     59};
19 int bit[40]={0,
20     1,1,1,2,1,
21     2,1,1,2,2,
22     1,1,2,2,1,
23     2,1,3,1,2,
24     2,2,1,2,2,
25     1,3,1,2,1,
26     2,1,2,2,2,
27     1};
28 int high[40]={0,
29     1000000000,1000000,3981,1000,372,
30     63,43,24,19,15,
31     13,8,7,6,6,
32     4,4,3,3,3,
33     3,3,3,2,2,
34     2,2,2,2,2,
35     2,2,2,2,2,
36     2};
37 
38 ll n;
39 
40 ll QP(ll a,int i){
41     ll ans=1,tmp=a;
42     while(i){
43         if(i&1)ans*=tmp;
44         tmp*=tmp;
45         i>>=1;
46     }
47     return ans;
48 }
49 
50 int check(int i){
51     int l=1,r=high[i];
52     while(l<=r){
53         int m=l+((r-l)>>1);
54         ll res=QP(m,num[i]);
55     //    printf("%d %d %d %lld
",l,r,m,res);
56         if(res<=n)l=m+1;
57         else r=m-1;
58     }
59     return r-1;
60 }
61 
62 int main(){
63 //    n=9;
64 //    printf("%d
",check(1));
65     while(scanf("%lld",&n)!=EOF){
66         ll ans=1;
67         for(int i=1;i<=pnum;++i){
68 //            printf("%d
",check(i));
69             if(bit[i]%2)ans+=check(i);
70             else ans-=check(i);
71         }
72         printf("%lld
",ans);
73     }
74     return 0;
75 }
View Code
原文地址:https://www.cnblogs.com/cenariusxz/p/6592356.html