题目链接:https://cn.vjudge.net/problem/UVA-11752
We all know the Super Powers of this world and how they manage to get advantages in political warfare or even in other sectors. But this is not a political platform and so we will talk about a different kind of super powers — “The Super Power Numbers”. A positive number is said to be super power when it is the power of at least two different positive integers. For example 64 is a super power as 64 = 82 and 64 = 43 . You have to write a program that lists all super powers within 1 and 264 − 1 (inclusive).
Input
This program has no input. Output Print all the Super Power Numbers within 1 and 264 − 1. Each line contains a single super power number and the numbers are printed in ascending order. Note: Remember that there are no input for this problem. The sample output is only a partial solution. Sample Input Sample
Output
1
16
64
81
256
512
.
.
.
题目翻译:
求1到2的64次方-1范围内所有的超级数(满足条件:有两个以上不同的幂次方)
网上的解释(比较暴力并且经典的做法):
直接扫描2~(2^16-1)内的所有数字,设为i。
设指数为j,令j=4,检查所有大于等于4,并且使i^j<=(2^64-1)成立的j。
i^j<=(2^64-1)可化为j<=ln(2^64-1)/ln(i)。(为了防爆long long,可以用double)
这有有个需要注意的地方。double可以表示1.7* 10的300次方,但不能准确表示1.7* 10的300次方加上1那个数。按科学计算法书写,double可以有15位有效数字。
所以2^64-1并不能用double精确表示。可以用ln(2^64-1)减小误差。(只能减小,不能完全消除)
#include <cstdio>
#include <cmath>
#include <set>
#define ull unsigned long long
#define db double
using namespace std;
set<ull> ss;
int judge(int x){
for(int i=2;i*i<=x;i++)
if(x%i==0)
return 1;
return 0;
}
ull quick_pow(ull a, int b){
ull res=1;
while(b){
if(b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
int main()
{
db s=pow(2,64)-1;
ss.insert(1);
for(int i=2;i<(1<<16);i++)
for(int j=4;j<(int)ceil(log(s)/log(i*1.0));j++)
if(judge(j))
ss.insert(quick_pow((ull)i,j));
for(set<ull>::iterator it=ss.begin();it!=ss.end();it++)
printf("%llu\n",*it);
return 0;
}