算法优化
Optimization of Algorithm
这是问题的链接。
该问题询问形式为 1/x + 1/y = 1/z 的丢番图方程的解数(其中 z = n!重新排列给定的方程清楚地表明答案是 z2 的因子数。
所以问题归结为找到 n 的因子数!2(n 阶乘平方)。
我的算法如下
- 使用埃拉托色尼筛算法为所有素数 <= n 创建一个布尔查找表。
- 遍历所有素数 P <= n,并在 n! 中找到它的指数。 我使用步进函数公式执行此操作。设指数为 K,然后是 n 中 P 的指数!2 将是 2K。
- 使用步骤 2 使用标准公式计算因子数。
对于 n = 106 的最坏情况输入,我的 c 代码在 0.056s 内给出答案。我想复杂性不会比O(n lg n)大。但是当我在网站上提交代码时,我只能通过 3/15 个测试用例,其余的测试用例在超过时间限制时做出裁决。
我需要一些提示来优化此算法。
到目前为止的代码:
#include <stdio.h>
#include <string.h>
#define ULL unsigned long long int
#define MAXN 1000010
#define MOD 1000007
int isPrime[MAXN];
ULL solve(int N) {
int i, j, f;
ULL res = 1;
memset(isPrime, 1, MAXN * sizeof(int));
isPrime[0] = isPrime[1] = 0;
for (i = 2; i * i <= N; ++i)
if (isPrime[i])
for (j = i * i; j <= N; j += i)
isPrime[j] = 0;
for (i = 2; i <= N; ++i) {
if (isPrime[i]) {
for (j = i, f = 0; j <= N; j *= i)
f += N / j;
f = ((f << 1) + 1) % MOD;
res = (res * f) % MOD;
}
}
return res % MOD;
}
int main() {
int N;
scanf("%d", &N);
printf("%llun", solve(N));
return 0;
}
这里有
一个int
溢出:
for (j = i, f = 0; j <= N; j *= i)
如果46340 < i < 65536
并且对于许多较大的i
,在第二次迭代中,如果溢出环绕,j
将为负数(这是未定义的行为,因此任何事情都可能发生)。
将其替换为例如
for(j = N / i, f = 0; j > 0; j /= i) {
f += j;
}
但是,由于溢出而导致的额外迭代不太可能导致"超出时间限制",这很可能只会导致错误的结果。
所以通用建议是
- 只筛奇数,也许也可以从筛子中消除 3 的倍数。从筛子中消除奇数大约使筛分所需的时间减半。
- 不要使用整个
int
作为标志,使用位或至少char
秒。这提供了更好的缓存局部性和进一步的加速。
相关文章:
- std::stable_sort: 如何选择内存优化算法而不是时间优化算法?
- 解析参数后内联以优化算法速度
- 如何优化标准::设置交集算法(C++)
- 优化的图像卷积算法
- 优化德劳奈三角测量算法
- 优化查找特定斐波那契数的算法
- 基本算法优化
- "Neighbor function"优化以使用A*算法解决8难题
- 优化算法以查找满足某些属性的六位数字的数量
- 利用优先级队列C++优化了从O(n^2)到O(n)的Huffman树算法
- STL算法是否针对速度进行了优化
- 优化最近邻居大小调整算法以提高速度
- 优化算法"binary_fold"并使其左(或右)关联
- 优化算法以检查"Whether for a given directed graph there is only one way to sort the graph using topological
- 优化算法
- 非常简单的优化算法产生一个函数参数误差
- 使用正确的优化算法C++在三维空间中查找点之间的距离
- 需要优化 - 算法实现占用太多内存
- 计算乘数和除数值的优化算法
- 我如何优化算法和条件在这个for循环