Problem Description
让你编写一个程序,求出1到2^64-1范围内的,所有超级力量数。超级力量数满足,可以分解为两个以上数的幂。例如64 = 8^2 = 4^3。两个以上所以64满足。
思路:
x^y,只要y不是素数,y就可以分解为两个数的乘积。这样就肯定有两个以上的数的幂满足。
要注意数据范围 2^64得用无符号unsigned long long。y最小是4。那么x最大就是2^16。
x^y <= 2^64 -> ylog(x) <= 64log(2) -> y = 64*log(2) / log(x)
对于每个x, y最大为ceil(64*log(2) / log(x)) - 1;
ceil函数:返回大于或者等于指定表达式的最小整数
#include<bits/stdc++.h>
using namespace std;
#define nn (1<<16) + 2
#define ll unsigned long long
int vis[nn];
ll Pow(ll a, ll n)//快速幂
{
ll sum = 1;
while(n)
{
if(n&1) sum *= a;
a = a*a;
n >>= 1;
}
return sum;
}
void get_prime()//打素数表
{
memset(vis, 0, sizeof(vis));
vis[1] = vis[0] = 1;
for(ll i = 2; i*i < nn; i++)
{
if(!vis[i])
for(ll j = 2*i; j < nn; j = j+i)
vis[j] = 1;
}
}
int main()
{
get_prime();
set<ll> q;
set<ll>::iterator it;
q.insert(1);//1也是,所以先入
for(ll i = 2; i < nn; i++)
{
double t = ceil(1.0*64/log(i)*log(2)) - 1;//因为最大为2^64 - 1。所以向上取整-1
if(i == 10) break;
for(ll j = 4; j <= t; j++)
{
if(!vis[j]) continue;
q.insert(Pow(i, j));
}
}
for(it = q.begin(); it != q.end(); it++)
{
printf("%llu\n", *it);
}
return 0;
}