数论 + 离散化 - The Super Powers - UVA 11752
题意:
若 一 个 数 能 够 转 化 为 两 个 不 同 正 整 数 的 幂 , 则 称 这 个 数 是 若一个数能够转化为两个不同正整数的幂,则称这个数是 若一个数能够转化为两个不同正整数的幂,则称这个数是 The Super Power Numbers
例 如 : 64 = 8 2 = 4 3 例如:64=8^2=4^3 例如:64=82=43
输 出 [ 1 , 2 64 − 1 ] 以 内 的 所 有 S u p e r P o w e r N u m b e r s 输出[1,2^{64}-1]以内的所有Super\ Power \ Numbers 输出[1,264−1]以内的所有Super Power Numbers
Sample Input
Sample Output
1
16
64
81
256
512
.
.
.
分析:
假 设 正 整 数 X = P k , 若 X 为 S u p e r P o w e r N u m b e r s , 必 有 X = P 1 k 1 k , 假设正整数X=P^{k},若X为Super\ Power \ Numbers,必有X=P_1^{k_1k}, 假设正整数X=Pk,若X为Super Power Numbers,必有X=P1k1k,
其 中 P = P 1 k 1 , 且 k 1 ≥ 2 其中P=P_1^{k_1},且k_1\ge 2 其中P=P1k1,且k1≥2
这 意 味 着 k 是 一 个 大 于 2 的 合 数 。 这意味着k是一个大于2的合数。 这意味着k是一个大于2的合数。
且 k 的 上 界 是 64 , 下 界 是 4 。 且k的上界是64,下界是4。 且k的上界是64,下界是4。
因 此 , 我 们 暴 力 枚 举 底 数 到 ( 2 64 − 1 ) 1 4 , 指 数 到 64 , 再 判 断 即 可 。 因此,我们暴力枚举底数到(2^{64}-1)^{\frac{1}{4}},指数到64,再判断即可。 因此,我们暴力枚举底数到(264−1)41,指数到64,再判断即可。
将 所 有 符 合 条 件 的 数 保 存 下 来 , 排 序 再 判 重 , 最 后 输 出 。 将所有符合条件的数保存下来,排序再判重,最后输出。 将所有符合条件的数保存下来,排序再判重,最后输出。
注意:
边 界 位 置 需 要 格 外 注 意 , 在 枚 举 指 数 的 时 候 可 能 会 爆 u l l 。 边界位置需要格外注意,在枚举指数的时候可能会爆ull。 边界位置需要格外注意,在枚举指数的时候可能会爆ull。
解 决 方 案 , 当 x i > i n f 时 退 出 , 为 了 防 止 溢 出 , 可 在 前 一 次 循 环 , 当 x i > i n f / x 时 提 前 退 出 。 解决方案,当x^i>inf时退出,为了防止溢出,可在前一次循环,当x^i>inf/x时提前退出。 解决方案,当xi>inf时退出,为了防止溢出,可在前一次循环,当xi>inf/x时提前退出。
代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ull unsigned long long
using namespace std;
const int N=100010;
const ull inf=(1<<64)-1;
ull ans[N], idx;
bool check(int x)
{
for(int i=2;i<=x/i;i++)
if(x%i==0)
return false;
return true;
}
void cal(ull x)
{
ull tmp=1;
for(int i=1;i<=64;i++)
{
tmp*=x;
if(!check(i)) ans[idx++]=tmp;
if(tmp>inf/x) break;
}
}
int main()
{
ans[idx++]=1;
for(int i=2;i<=65536;i++) cal(i);
sort(ans,ans+idx);
int n=unique(ans,ans+idx)-ans;
for(int i=0;i<n;i++) printf("%llu\n",ans[i]);
return 0;
}