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 Input10361000000000000000000 Sample Output491001003332
新闻热点
疑难解答