题目链接:https://vjudge.net/problem/UVA-11752
题意:
一个超级数是能够至少能表示为两个数的幂,求1~2^64-1内的超级数。
题解:
1.可知对于 n = a^b,如果b是合数,那么n同样可以表示为: n = (a^k)^c,其中k*c = b。所以只需要枚举底数,然后再枚举指数,如果指数为合数,那么它就是一个超级数。
2.由于2^64-1已经是 unsigned LL 的最大值了,为了避免溢出,指数应该从当前底数能达到的最大指数开始枚举。
3.由于一个超级数可能被多次访问到,所以用STL的 set 可以解决重复、离散化的问题,而且还能排序。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 #define ms(a,b) memset((a),(b),sizeof((a))) 13 using namespace std; 14 typedef long long LL; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int mod = 1e9+7; 18 const int maxn = 1e5+100; 19 20 int vis[100]; 21 void init() 22 { 23 int m = sqrt(64+0.5); 24 for(int i = 2; i<=m; i++) if(!vis[i]) { 25 for(int j = i*i; j<64; j += i) 26 vis[j] = 1; 27 } 28 } 29 30 typedef unsigned long long ull; 31 set<ull>s; //用set完成了排序加去重的功能 32 int main() 33 { 34 init(); //标记在64以为的合数 35 for(ull i = 2;; i++) //枚举底数 36 { 37 int t = ceil(64*log(2)/log(i)) - 1; 38 if(t<4) break; 39 ull x = 1; 40 for(int j = 1; j<=t; j++) 41 { 42 x *= i; 43 if(vis[j]) s.insert(x); 44 } 45 } 46 47 s.insert(1); 48 set<ull>::iterator it; 49 for(it = s.begin(); it!=s.end(); it++) 50 cout<<*it<<endl; 51 }