题目内容:
Ignatius 喜欢收集蝴蝶标本和邮票,但是Eddy的爱好很特别,他对数字比较感兴趣,他曾经一度沉迷于素数,而现在他对于一些新的特殊数比较有兴趣。 这些特殊数是这样的:这些数都能表示成M^K,M和K是正整数且K>1。 正当他再度沉迷的时候,他发现不知道什么时候才能知道这样的数字的数量,因此他又求助于你这位聪明的程序员,请你帮他用程序解决这个问题。 为了简化,问题是这样的:给你一个正整数N,确定在1到N之间有多少个可以表示成M^K(K>1)的数。
输入描述
本题有多组测试数据,每组包含一个整数N,1<=N<=1000000000000000000(10^18).
输出描述
对于每组输入,请输出在在1到N之间形式如M^K的数的总数。 每组输出占一行。
输入样例
10 36 1000000000000000000
输出样例
4 9 1001003332
一开始想了个法儿,从2开始循环判断每个数字,如果可以形成m的k次方就return true计数,但是这样会超时的
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
bool judge(ll n){
for(ll i = sqrt(n); i >= 2; i--){
ll temp = i * i;
while(1){
if(temp == n) return true;
else if(temp > n) break;
else if(temp < n) temp = temp * i;
}
}
return false;
}
int main(){
ll n;
int count;
while(cin>>n){
count = 1;
for(ll ii = 2; ii <= n; ii++){
if(judge(ii)){
cout<<ii<<endl;
count++;
}
}
cout<<count<<endl;
}
}
看了一下容斥原理,然而不是很懂该怎么应用在算法里
看了一个大牛的博客,看了一下午!!!终于搞懂了!!!
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
int count = 0;
int i;
ll n;
int sushu[60] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59}; //17个素数,因为2的60次方超范围了
/*
容斥原理
我首先是这样想的,我们算1 - n之间的满足条件的数的个数,要算
以2,3,4,5,6……为指数时有多少底数满足,然后相加
这样的想法显然是错的呀,因为有很多重复eg. 4^2 = 2^4
然后我们发现,M^k = M^(k' * p) p为质数
就是说,如果指数为合数,就可以表示为一个质数和另一数的积,就可以转化为以这个质数为指数
所以我们考虑以2,3,5,7,11……这样的质数为指数时有多少底数满足,然后相加
但是还是会有重复,因为8^2 = 4^3 因为他们都是2^6,所以我们要将 指数是两个质数的积的数减去
根据容斥定理,应该将以一个质数做指数的时候的所有情况相加 - 以两个质数的积作指数的情况相加 + 以三个质数为积的指数的情况相加
(由于^60 > 10^18,所以只考虑小于60的质数,又因为2*3*5*7 > 60,所以只考虑三个质数的积为指数的情况)
*/
void dfs(int z, int num, int p){//z是指数数组的下标
if(p == 0){
ll t = pow(n, 1.0 / num);//计算当num为指数时,底数最大为多少
if(pow(t, 0.0 + num) > n) t--;//如果底数的num次方大于n就减掉这种情况
t--;//由于1在每个集合里都符合所以先在计算时减去,再在cout中加上
if(t > 0)
count += t * ((i & 1) ? 1 : -1);//位与运算判断奇偶性,如果是1个质数和三个质数就+,2个质数的积就减
return;
}
if(z >= 17) return;//如果下标过了16就终结
if(num * sushu[z] < 60)//如果指数还在范围内就向下搜
dfs(z + 1, num * sushu[z], p - 1);
dfs(z + 1, num, p);
}
int main(){
while(cin>>n){
count = 0;
for(i = 1; i <= 3; i++){
dfs(0,1,i);//i表示构成指数的素数的个数
}
cout<<count + 1<<endl;//加上1这种情况
}
return 0;
}