c - 找到两个连续的素数,使得它们之间的间隔大于或等于 N
问题描述
我正在编写一个程序来读取整数 n (0 < n <= 150) 并找到最小的素数 p 和连续素数 q,使得 q - p >= n。
我的代码有效,但对于较大的 n,它运行大约 10 秒。
#include <stdio.h>
#include <stdlib.h>
int isPrimeRecursive(int x, int i){
if (x <= 2){
return (x == 2 ? 1:0);
}
if (x % i == 0){
return 0;
}
if (i * i > x){
return 1;
}
return isPrimeRecursive(x, i+1);
}
int findSuccessivePrime(int x){
while (1){
x++;
if (isPrimeRecursive(x, 2)){
return x;
}
}
return 0;
}
int findGoodGap(int n, int *arr){
int prime = findSuccessivePrime(n*n);
while (1){
int gap;
int succPrime;
succPrime = findSuccessivePrime(prime);
gap = succPrime - prime;
if (gap >= n){
arr[0] = succPrime;
arr[1] = prime;
return gap;
}
prime = succPrime;
}
return 0;
}
int main(int argc, char *argv[]){
int n;
int arr[2];
scanf("%d", &n);
int goodGap;
goodGap = findGoodGap(n, arr);
printf("%d-%d=%d\n", arr[0], arr[1], goodGap);
return 0;
}
如何让程序更有效率?我只能使用 stdio.h 和 stdlib.h。
解决方案
该算法非常低效。你一遍又一遍地重新计算相同的东西。你可以这样做:
int n;
// Input n somehow
int *p = malloc(n * sizeof *p);
for(int i=0; i<n; i++) p[i] = 1; // Start with assumption that all numbers are primes
p[0]=p[1]=0; // 0 and 1 are not primes
for(int i=2; i<n; i++)
for(int j=i*2; j<n; j+=i) p[j] = 0;
现在,p[i]
可以将其视为判断是否i
是素数的布尔值。
以上可以进一步优化。例如,当您已经删除了所有可被 2 整除的数字时,删除所有可被 4 整除的数字是毫无意义的。这是一个非常简单的 mod:
for(int i=2; i<n; i++) {
while(i<n && !p[i]) i++; // Fast forward to next prime
for(int j=i*2; j<n; j+=i) p[j] = 0;
}
正如 Yom B 在评论中提到的,这是一种记忆模式,您可以在其中存储结果以备后用,这样我们就不必重新计算所有内容。但是动态编程更进一步,这基本上意味着使用记忆作为算法本身的一部分。
在 C64 演示场景中大量使用的纯记忆的一个示例是预先计算三角函数的值表。甚至使用简单的乘法表,因为 C64 处理器的乘法比简单的查找要慢得多。一个缺点是更高的内存使用率,这是旧机器上的一个大问题。
推荐阅读
- javascript - 构建计算器,获取无法设置属性“值”为空
- c# - subscriptionClient.AbandonAsync 与 subscriptionClient.closeAsync
- excel - Excel - 逐行到逐列的转换
- r - 如何更改在R中重复多次的特定变量的名称
- python - 同一索引中的多个单个列表
- python-3.x - 验证python中嵌套列表的输入
- mysql - MYSQL 如何在 24 小时内按小时获取数据组,即使数据不存在,IF 0 将选择 NULL
- python-3.x - 将列更改为数据
- docker - 在 docker 上运行时无法启动 Redis 服务
- node.js - 如何在 DialogFlow 中接收 Kommunicate 发送的数据?