首页 > 学院 > 开发设计 > 正文

hdoj 2204 Eddy's爱好(容斥)

2019-11-09 20:58:03
字体:
来源:转载
供稿:网友

http://acm.hdu.edu.cn/showPRoblem.php?pid=2204

给定n,求1-n中有多少个可以表示成M的K次方的数。K>1

题意很简单,但是怎么想?题面上说到了素数,第一想法就是K从素数开始枚举!

当K不是素数时,必然是重复算过的!比如K=6时,一定会有一个(M1的2次方)的3次方=(M2的3次方)的2次方

那么,最大素数是多少?n最大值是1e18,所以呢,找到一个x,使得2的x次方大于n的最大值,x=60

所以取61为最大素数肯定满足条件了

可以枚举了?

还是要注意容斥!

例如15=3*5,所以,3的要加,5的要加,15的要减

最多是几层?

2*3*5=30

2*3*5*7=210已经大于60了,所以最多枚举三重循环就好

现在是有了n和K,怎么得到M呢?

只需要这一行代码:

[cpp] view plain copytmp=(int)(pow((double)n,1.0/prime[i])+eps);  最后1个问题:1的K次方都是满足条件的

所以,注意:一开始ans赋初始化就为1,之后,所有的计算把1除掉就好

转自:点击打开链接

代码:

#include<iostream>#include<cmath>#include<cstdio>using namespace std;typedef long long ll;const double eps = 1e-9;int prime[18] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61};ll ans, n;void dfs(int cur, int ex, int pos){    if(pos > 3) return ;    for(int i = cur; i < 18; i++)    {        ll num = pow(n, 1.0/(ex*prime[i]))+eps;        num--;        if(num > 0)            ans += num*(pos%2 ? 1 : -1);        dfs(i+1, ex*prime[i], pos+1);    }}int main(void){    while(cin >> n)    {        ans = 0;        dfs(0, 1, 1);        printf("%lld/n", ans+1);    }    return 0;}

Eddy's爱好

Time Limit: 3000/1000 MS (java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2433    Accepted Submission(s): 1116Problem DescriptionIgnatius 喜欢收集蝴蝶标本和邮票,但是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
10361000000000000000000 Sample Output
491001003332 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表