HDU 2204 Eddy's爱好(容斥原理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2204

解题报告:输入一个n让你求出[1,n]范围内有多少个数可以表示成形如m^k的样子。

不详细说了,自己一开始也忽略了三个素数的乘积的乘方的情况。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long INT;
 8 INT prim[70];
 9
10 int dabiao()
11 {
12     int f = 0;
13     for(int i = 2;i < 60;++i)
14     {
15         int flag = 1;
16
17         for(int j = 2;j < i;++j)
18         if(i % j == 0)
19         {
20             flag = 0;
21             break;
22         }
23         if(flag) prim[f++] = i;
24     }
25     return f;
26 }
27
28 int calc(INT a,INT b,INT n)
29 {
30     INT s = 1;
31     while(b--)
32     {
33         if((INT)(n / a) <= s) return 0;
34         s *= a;
35     }
36     return 1;
37 }
38 int main()
39 {
40     INT n;
41     int num = dabiao();
42     while(scanf("%I64d",&n)!=EOF)
43     {
44         INT tot = 1;
45         for(int i = 0;i < num;++i)
46         {
47             INT temp = (INT)pow((double)n,1.0 / prim[i]);
48             if(temp == 1 ) break;   //开方之后不足1的话,则退出
49             tot += temp - 1;   //减1是因为每次都会统计到1
50         }
51         for(int i = 0;i < num;++i)
52         for(int j = i+1;j < num;++j)
53         {
54             INT temp = pow((double)n,1.0/(prim[i] * prim[j]));
55             if(temp == 1) break;
56             tot -= temp - 1;
57         }
58         for(int i = 0;i < num;++i)
59         for(int j = i + 1;j < num;++j)
60         for(int k = j + 1;k < num;++k)
61         {
62             INT temp = pow((double)n,1.0/(prim[i] * prim[j] * prim[k]));
63             if(temp == 1) break;
64             tot += temp - 1;
65         }
66         printf("%I64d\n",tot);
67     }
68     return 0;
69 }

HDU 2204 Eddy's爱好(容斥原理)

时间: 2024-10-25 22:25:56

HDU 2204 Eddy's爱好(容斥原理)的相关文章

[容斥原理] hdu 2204 Eddy&#39;s爱好

题意: 中文题目! 思路: 首先 M^k可以分解成 (M^(k*p)) p是素数 这么我们只要枚举素因子就好了 由于数据 所以只要枚举60以内的素数就够了 然后因为2*3*5*7就超过60了 做容斥原理就最多就只有三次 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #inclu

【容斥】 HDU 2204 Eddy&#39;s爱好

通道 题意:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数. 思路:我们可以由n^(1/p),知道指数为p的有多少个数. 通过观察,可以发现若一个数可以表示成x^(k*t),则可以表示成(x^k)^t.因此指数必然为素数. 枚举素数便可以得到指数为p的个数,但是可能出现重复,例如:x^3=y^5,其中x=t^5,y=t^3. 运用容斥原理,设a[i]表示指数为第i个素数的个数,那么答案等于满足一个的,减去两个的,加上三个的…… 由于2^60>10^18,2*3*5*7

hdu2204 Eddy&#39;s爱好 打表+容斥原理

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

HDU2204 Eddy&#39;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}$还是不可

C - Eddy&#39;s爱好

C - Eddy's爱好 Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatus Description Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣. 这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1. 正当他再度沉迷的时候,他发现不知道什么时候才能知道

【HDU2204】Eddy&#39;s爱好

题目大意:求从 1 到 N 中共有多少个数可以表示成 \(M^K,K \gt 1\).\(N \le 1e18\) 题解: 发现 N 很大,若直接枚举 M 的话有 1e9 级别的数据量,肯定超时,因此考虑枚举幂次.发现对于幂次为 k 的符合条件的数有 N 开 K 次方下取整个,同时注意到 k 的取值范围最大为 60,因为 2 的 60 次方为 1e18 级别.因此考虑从小到大进行枚举幂次即可,但是发现有些数字会产生重复,如:\((2^3)^2=(2^2)^3=2^6\),即:同一个数字被计入了三

HDU 1163 Eddy&#39;s digital Roots

Eddy's digital Roots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5783    Accepted Submission(s): 3180 Problem Description The digital root of a positive integer is found by summing the digit

杭电 HDU 1164 Eddy&#39;s research I

Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7117    Accepted Submission(s): 4268 Problem Description Eddy's interest is very extensive, recently  he is interested in prime

hdu 1210 Eddy&#39;s 洗牌问题

Problem Description Eddy是个ACMer,他不仅喜欢做ACM题,而且对于纸牌也有一定的研究,他在无聊时研究发现,如果他有2N张牌,编号为1,2,3..n,n+1,..2n.这也是最初的牌的顺序.通过一次洗牌可以把牌的序列变为n+1,1,n+2,2,n+3,3,n+4,4..2n,n.那么可以证明,对于任意自然数N,都可以在经过M次洗牌后第一次重新得到初始的顺序.编程对于小于100000的自然数N,求出M的值. Input 每行一个整数N Output 输出与之对应的M Sa