题目大意是在1~2^64-1的范围内找到所有符合条件的数,条件要求这个数字是两个或两个以上不同数字的幂,例如64=8^2=4^3。

对于这一题,分析是:如果一个满足这个条件的数字一定可以转换成i^k,而且k是一个合数。同时,幂指数的上限在1~64中,这一点是通过观察筛选数字的范围

所得出的。综上,幂指数k的限定条件是(1<=k<=64,k为合数)。那么在正式筛选数字前可以通过素数筛选从而来标记出1~64中所有的合数,而对于每一种情况的幂指数就是ceil(log(2^64)/log(i))=ceil(64*(log(2)/log(i)))。

接下来需要限定的是底数的范围。我们的筛选范围的最大值也就是2^64-1,而幂指数的最小值为4,所以底数的最大值为2^16-1。则底数的范围就是1~2^16-1.

ps:2^16=1<<16;

剩下的事情就是枚举所有可能的情况,值得一提的是这里用到STL中的set可以节省很多的代码,因为set的特性就是里面的数据不重复而且是按从小到大的顺序排列的。

#include <cstdio>
#include <iostream>
#include <cmath>
#include <set>
#include <string>
#include <iterator>
#include <algorithm>
typedef unsigned long long LL;
using namespace std;
int index[100]={ 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26,
    27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46,
    48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 64};
set<LL> ans;
int main()
{
    LL maxt=1<<16,i;
    LL temp;
    int maxindex,j;
    ans.clear();
    printf("1\n");
    for(i=2;i<maxt;i++)
    {
        temp=i*i*i*i;
        ans.insert(temp);
        maxindex=ceil(64*(log(2)/log(i)))-1;//计算每数的幂指数的最大值
        for(j=1;index[j]<=maxindex;j++)//筛选出每个数的幂中符合要求的数
        {
           if(index[j]-index[j-1]==1)
            temp=temp*i;
           else
            temp=temp*i*i;
           ans.insert(temp);
        }
    }
    for(set<LL>::iterator iter=ans.begin();iter!=ans.end();iter++)
        cout<<*iter<<endl;//这题用printf输出会出现数据丢失而且笔者未能找到有效的解决办法,若有人找到了请回复笔者怎么解决,感激不尽,此处建议用cout输出。
    return 0;
}