题目大意是在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; }
时间: 2024-11-09 10:12:17