UVA11752 The Super Powers —— 数论、枚举技巧

题目链接: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 }
View Code
原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8391584.html