
2026-07-21:可由多种立方和构造的整数。用go语言,给定一个正整数上限 n,一个正整数 x 被称为“好整数”,当且仅当它可以表示为两组不同的正整数对 (a, b) 的立方和,其中 a 和 b 都是正整数且满足 a ≤ b。换句话说,存在至少两种不同的 (a, b) 组合,使得 x = a³ + b³。现在需要找出所有不超过 n 的好整数,并将它们按从小到大的顺序以列表形式返回。
1 <= n <= 1000000000。
输入: n = 4104。
输出: [1729,4104]。
解释:
在小于等于 4104 的整数中,好整数包括:
1729:1³ + 12³ = 1729,以及 9³ + 10³ = 1729。
4104:2³ + 16³ = 4104,以及 9³+ 15³ = 4104。
因此,答案是 [1729, 4104]。
题目来自力扣3890。
init 函数)mx = 1_000_000_000。a,从1开始枚举,直到a³ > mx/2为止。
为什么是mx/2?因为我们要找a³ + b³ ≤ mx且a ≤ b,当a³本身就超过mx/2时,即使最小的b = a,和也会超过mx,所以无需继续枚举。(a, b) 组合a,内层循环枚举 b(从 a 开始,保证 a ≤ b)。a³ + b³ > mx,一旦超过就 break 内层循环。(a, b),计算 x = a³ + b³,并在一个哈希表 cnt 中统计该值出现的次数。cnt,对于出现次数 c > 1 的 x,说明它至少可以由两组不同的 (a, b) 表示,因此将其加入 goodIntegers 列表。slices.Sort 将 goodIntegers 从小到大排序,以便后续二分查找。备注: 题目描述提到“两组不同的正整数对”,代码中当 c > 1 即判定为好整数。这是正确的,因为枚举时保证了 a ≤ b,所以同一个 x 如果有多个计数,必然对应不同的 (a, b) 组合(组合无序但已通过 a ≤ b 规范表示)。
findGoodIntegers 函数)sort.SearchInts(goodIntegers, n+1),在已排序的 goodIntegers 中查找第一个 大于 n 的元素的下标 i。goodIntegers 是升序的,所有下标 < i 的元素都 ≤ n。goodIntegers[:i],即所有不超过 n 的好整数,已经是有序的。n = 4104,调用 findGoodIntegers(4104) 得到 [1729, 4104],并打印。a 的范围:a³ ≤ 5e8(即 mx/2),所以 a 最大约 ∛(5e8) ≈ 793。b 的范围:对于每个 a,b 从 a 开始,直到 b³ ≤ mx - a³。
总枚举的 (a, b) 对的数量大约是所有满足 a ≤ b 且 a³ + b³ ≤ 1e9 的组合数。a³ + b³ ≤ 1e9,且 1 ≤ a ≤ b。u = a³, v = b³,则 u + v ≤ 1e9,且 u ≤ v,u 和 v 是立方数。O(N^(2/3)),这里 N = 1e9,所以 N^(2/3) = (1e9)^(2/3) = 1e6 级别。a³ + b³ 和哈希表操作为 O(1),所以预计算的总时间在可接受范围内,记为 O(M),其中 M 是满足条件的 (a, b) 对的数量(约 10^5 ~ 10^6)。cnt 存储所有可能的 a³ + b³ 值,不同值的数量小于等于 M,也是 O(M)。goodIntegers 存储出现次数 >1 的值,数量远小于 M(题目提到共 1554 个),可视为 O(G),G 是好整数数量。sort.SearchInts 时间复杂度 O(log G),G ≈ 1554,几乎常数时间。总结:
.
package main
import (
"fmt"
"slices"
"sort"
)
var goodIntegers []int// 1554 个
func init() {
const mx = 1_000_000_000
cnt := map[int]int{}
for a := 1; a*a*a <= mx/2; a++ {
for b := a; a*a*a+b*b*b <= mx; b++ {
cnt[a*a*a+b*b*b]++
}
}
for x, c := range cnt {
if c > 1 {
goodIntegers = append(goodIntegers, x)
}
}
slices.Sort(goodIntegers)
}
func findGoodIntegers(n int) []int {
i := sort.SearchInts(goodIntegers, n+1)
return goodIntegers[:i]
}
func main() {
n := 4104
result := findGoodIntegers(n)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
def init_good_integers():
"""初始化好整数列表,这些数可以用至少两种方式表示为两个立方数之和"""
mx = 1_000_000_000
cnt = {}
a = 1
while a * a * a <= mx // 2:
b = a
while a * a * a + b * b * b <= mx:
val = a * a * a + b * b * b
cnt[val] = cnt.get(val, 0) + 1
b += 1
a += 1
good_integers = []
for x, c in cnt.items():
if c > 1:
good_integers.append(x)
good_integers.sort()
return good_integers
def find_good_integers(n, good_integers):
"""返回所有不大于 n 的好整数"""
result = []
for x in good_integers:
if x <= n:
result.append(x)
else:
break
return result
def main():
good_integers = init_good_integers()
n = 4104
result = find_good_integers(n, good_integers)
print(result)
if __name__ == "__main__":
main()
.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
vector<int> goodIntegers;
// 全局初始化器
namespace {
struct InitGoodIntegers {
InitGoodIntegers() {
const int mx = 1'000'000'000;
unordered_map<int, int> cnt;
for (int a = 1; a * a * a <= mx / 2; a++) {
for (int b = a; a * a * a + b * b * b <= mx; b++) {
int val = a * a * a + b * b * b;
cnt[val]++;
}
}
for (const auto& [x, c] : cnt) {
if (c > 1) {
goodIntegers.push_back(x);
}
}
sort(goodIntegers.begin(), goodIntegers.end());
}
} initGoodIntegers;
}
vector<int> findGoodIntegers(int n) {
auto it = upper_bound(goodIntegers.begin(), goodIntegers.end(), n);
int idx = distance(goodIntegers.begin(), it);
return vector<int>(goodIntegers.begin(), goodIntegers.begin() + idx);
}
int main() {
int n = 4104;
vector<int> result = findGoodIntegers(n);
cout << "[";
for (size_t i = 0; i < result.size(); i++) {
cout << result[i];
if (i < result.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
return 0;
}
