题目链接https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2852
思路:由可被两个幂次表示知,指数必定为合数,而64以内的合数很好确定,最小的指数必定为4
故直接找最大不超过1<<16即可。
用set排序,需注意使用unsigned long long,输出的格式控制符要注意,运算中防止乘法溢出。
#include<bits/stdc++.h>
#define LL unsigned long long
const int maxn = 0;
const LL limit= ~0LL >> 1;
using namespace std;
int main()
{
set<LL>s;
set<LL>::const_iterator it;
int prime[64],i,j,tot=0;
bool vis[65];
memset(vis,0,sizeof(vis));
for(i = 2; i<=64; i++)
{
if(!vis[i])
prime[tot++]=i;
for(j = 0; j<tot&&prime[j]*i<=64; j++)
{
vis[prime[j]*i]=true;
if(i%prime[j]==0)
break;
}
}
s.insert(1);
for(i = 2;i<=1<<16; i++)
{
LL temp=(LL)i*(LL)i*(LL)i; //可能溢出
LL x=limit;
int c=-1;
while(x)
{
x/=i;c++;
}
for(j = 4;j<=c;j++)
{
temp*=i*1ll;
if(vis[j]) s.insert(temp);
}
}
for(it=s.begin();it!=s.end();it++)
printf("%llu\n",*it);
}