The Super Powers UVA - 11752(算数基本定理+枚举+细节)

The Super Powers UVA - 11752

题意:

我们称一个可以由至少两个不同的正整数的幂的形式表示的数称为超级幂。没有输入,让你输出 1 2 64 1 之间的所有的超级幂。

分析:

根据算数基本定理,我们知道一个数可以分解成素数幂的乘积,那么既然一个数可以表示成某一个数的幂的形式那么肯定有

( p 1 p 2 . . . p r ) m

而如果可以表示成至少两个数的乘积,那么m肯定是个合数

注意!!!!m是合数,而1既不是质数也不是合数
我们在素数筛选的时候选的是质数,把质数标记为true,把非质数标记为另一个值,通常会把1变成false,但是如果我们选合数肯定是用! isprime[i]看,这个时候1就会浑水摸鱼进入合数范围!!所以1
也记为true就行,我在这里wa了好几次.

继续我们的分析: a m
底数最小为2,此时指数正如题目所给最大为64
指数最小为4(最小的合数),此时我们可以算出底数最大为 2 16 ( ( 2 16 ) 4 = 2 64 )

所以直接枚举就可以了

最后一定要注意数据范围longlong是有符号长整形,范围是 2 63 1 即一半一半,要想让范围是 2 64 1 必须用无符号长整形unsinged long long,整形int也是同理!!!!

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
typedef unsigned long long ll;
const int maxn = 64+5;
ll INF = (1<<64) - 1;
bool isprime[maxn];
void getPrime(){
    int n = 64;
    memset(isprime,true,sizeof(isprime));
    //isprime[0] = isprime[1] = false;注意这句不能有,否则会把1当成合数
    for(int i = 2; i * i <= n; i++){
        if(isprime[i]){
            for(int j = i+i; j <= n; j += i){
                isprime[j] = false;
            }
        }
    }
}
set<ll> s;
int main(){
    getPrime();
    for(int i = 2; i <= 65536; i++){
        ll ans = 1;
        for(int j = 1; j <= 64; j++){
            ans *= i;
            if(!isprime[j]) s.insert(ans);//问题出现在这里
            if(ans > INF / i) break;
        }
    }
    s.insert(1);
    set<ll>::iterator it;
    for(it = s.begin(); it != s.end(); it++){
        cout << *it << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/81121890