一、题目描述
二、算法分析说明与代码编写指导
以下全体字母均代表整数,^ 代表乘方。
设 n = a^s = b^t,a ≠ b,那么 a、b 含有的质因子是相同的,只是次数不同。设 n = x^y,因为 s ≠ t 且 s、t ≥ 2,所以 y ≥ LCM(2, 4) = 4。由于 n < 2^64,所以 x < 2^16 = 65536。x 也和 a、b 具有相同的质因子。
先用反证法证明 y ≥ s、t。
设 y < s 或 t,那么当 x 是质数时,a、b 只能是 x 的倍数,但此时不满足 x^y = a^s = b^t :a 或 b > x 意味着 a 或 b 含有 x 不含有的质因子,显然不能让这个等式成立;如果 a、b ≤ x,即 a、b = x,那么由于限制了 s ≠ t,等式自然也不成立。
当 x 是合数时,如果 x 含有次数仅为 1 的质因子,由于 y < s 或 t,但又要求 x^y = a^s = b^t,且已知 x、a、b 均含相同的质因子,为了使这个等式成立就得让 a、b 含有的这个质因子的次数小于 1,但这是不允许的。如果 x 不含次数仅为 1 的质因子,那么 x^y 可以写成 x’^y’,其中 x’ < x,y’ > y。若依然有 y’ < s 或 t,此时 x’、y’ 亦适用刚才描述的“x 含有次数为 1 的质因子……”的情形。
然后证明当 y 是质数时,不存在满足 x^y = a^s = b^t 的 a、b、s、t。
已知 y ≥ s、t,且 y 是质数。那么 s、t 均不能整除 y,所以无法找到这样的正整数解。
现在只剩下了 y 是合数的情况。y 是合数,就总是能成为 ≥ 2 的 s 和 t 两个公倍数,使得 x^y = a^s = b^t 。此时 a、b 的各质因子的次数分别是 x 的 y/s 倍和 y/t 倍。
三、AC 代码(10 ms)
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#pragma warning(disable:4996)
using namespace std;
vector<unsigned long long> v;
unsigned long long X, yt, y[] = { 4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,999 };
template<class _Ty> inline _Ty Power(_Ty radix, _Ty exp) {
_Ty ans = 1;
while (exp) {
if (exp & 1)ans *= radix;
exp >>= 1, radix *= radix;
}
return ans;
}
int main() {
v.emplace_back(1);
for (unsigned long long x = 2; x < 65536; ++x) {
yt = 64 / log2(x); X = x * x; X *= X; v.emplace_back(X);
for (unsigned long long i = 1; y[i] <= yt; ++i) { X *= Power(x, y[i] - y[i - 1]); v.emplace_back(X); }
}
sort(v.begin(), v.end()); vector<unsigned long long>::iterator H = unique(v.begin(), v.end());
for (vector<unsigned long long>::const_iterator I = v.cbegin() + 1; I != H; ++I)printf("%llu\n", *I);
return 0;
}