1. 程式人生 > >UVA - 11752 The Super Powers 【超級冪+數論+暴力列舉】

UVA - 11752 The Super Powers 【超級冪+數論+暴力列舉】

題目傳送門

題目描述:稱一個可以由至少兩個不同正整數的冪的形式表示的數為超級冪。輸出1~2^64-1之間的所有超級冪。

解題思路:由數論基本定理可知,任何一個數都可以分解為素數的乘積。如果一個數可以表示為n^k且這個數為超級冪那麼指數k必須為合數(自然數中除了能被1和本身整除外,還能被其他的數整除的數)。設一個數由兩部分組成,底數和指數:

底數最小為2,那麼指數最大為64;

指數最小為4;那麼底數最大為2^16;

暴力列舉,利用容器set去重且從小到大自動排序

AC程式碼:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define inf 0x3f3f3f
typedef long long ll;
typedef unsigned long long ULL;
const int mod=1e9+7;
const ULL maxn=(1<<64)-1;
bool isprime[66];
void getprime()//找出將小於等於64的所有合數,並賦值為false
{
    memset(isprime,true,sizeof(isprime));
    for(int i=2;i<=64;i++)
        for(int j=2;j*j<=i;j++)
            if(i%j==0)
                isprime[i]=false;
}
set <ULL> s;
int main()
{
    getprime();
    s.insert(1);
    for(int i=2;i<=(1<<16);i++)//列舉底數
    {
        ULL ans=1;
        for(int j=1;j<=64;j++)//列舉指數
        {
            ans*=i;
            if(!isprime[j])
                s.insert(ans);
            if(ans>maxn/i)//防止ans大於邊界
                break;
        }
    }
    set <ULL>::iterator a;
    for(a=s.begin();a!=s.end();a++)//輸出所有超級冪
        cout<<*a<<endl;
    return 0;
}