这是我在某个在线评审平台上所做的一个问题。
找出从1到N的数字因子的最大总和。
例如,如果N为11,则答案为18.从1到11的因子总和最大的数字是10(1 + 2 + 5 + 10)。
我实施了一个看起来像筛子的相对简单的解决方案。 C ++中的代码如下所示:
for (int i = 1; i <= 1000000; ++i {
for (int j = i; j <= 1000000; j += i) {
num[j] += i;
}
mx[i] = max(num[i], mx[i - 1]);
}
每当用户查询某些N时,我都会输出mx[N]
。这个解决方案似乎是正确的。但是,对于较大的输入,它超过了时间限制(1s)。最大N为1,000,000,但用户可以查询1,000,000个不同的N值。上述代码是一个运行一次的预处理代码。
上面代码的复杂性是N + N / 2 + N / 3 + ... + 1,我想这是N Log N.我如何提高这段代码的复杂性?
感谢您的帮助。
答案 0 :(得分:2)
这个问题的答案是:Highly Abundant Number
您可以从此处获取序列:A002093
实际上,我检查了10 ^ 10以下的所有高数量是41平滑数,而10 ^ 13以下是61平滑数。
N平滑数可以将素数分解为N以下
您可以像这个算法一样搜索n-smooth数字(例如47-平滑数字低于10 ^ 16):
vector<int> p = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 };
vector<long long> s = { 1 }; long long lim = 10000000000000000;
for (int i = 0; i < p.size(); i++) {
vector<long long> w;
for (long long j : s) {
long long mul = j;
for (; mul <= lim; mul *= p[i]) w.push_back(mul);
}
s = w;
}
您可以在O(log N + log X)
中对N平滑数X进行分解,因此您可以为O(log N + log X)
计算divisor function。
我给出了我的代码的结果,例如,我计算了所有61平滑数字,低于10 ^ 13,在3.5秒内,使用1GB内存。