今天在东华oj上做了一道题,基础部分第40题:分拆素数和,涉及到素数。
我觉得题目不难,我是这样写的:
/*
T40 分拆素数和
算法概述:对于一个偶数num,从2到num/2 - 1依次测试拆分是否满足要求
*/
#include<stdio.h>
#include<math.h>
// 判断是否为素数
int isPrim(int x) {
int i = 0;
for (i = 2; i <= sqrt(x); i++) {
if (x % i == 0) {
return 0;
}
}
return 1;
}
int main() {
int T = 0;
int num = 0;
int i = 0;
int count = 0;
scanf("%d", &T);
while (T) {
scanf("%d", &num);
count = 0;
for (i = 2; i <= num / 2 - 1; i++) {
if (isPrim(i) == 1 &&
isPrim(num - i) == 1) {// 用于拆分的两数均为素数
count++;
}
}
printf("%d\n", count);
T--;
}
return 0;
}
上述代码中涉及到了素数的判断,我感觉每次都要从2到sqrt(x)测试太麻烦了,时间复杂度一下子就上去了。我想到之前好像在哪里见过判断素数比较快的方法,好像叫什么素数表,于是就去搜了下,果然找到了一种类似的办法:
要找出从2到n之间的所有素数,可以设置一个标记数组isPrime,isPrime[x]为0代表x不为素数,isPrime[x]为1代表x为素数,初始时数组均设置为1。然后从2到n-1逐个判断,若2到n-1的某个数x为素数,那么x的两倍,三倍,四倍,五倍……一直到k*i达到n之间的所有的数都不为素数了,因为它们除了1和本身,至少还有一个因数x。
稍微改下代码:
/*
T40 分拆素数和
算法概述:对于一个偶数num,从2到num/2 - 1依次测试拆分是否满足要求
*/
#include<stdio.h>
#include<math.h>
// 构建素数表
void primeArray(int primeFlag[], int n) {
if (n < 2)
return ;
int i = 0, j = 0;
int count = 0;
for (i = 0; i < n; i++) {
primeFlag[i] = 1;// 初始默认全为素数
}
for (i = 2; i < n; i++) {
if (primeFlag[i] == 1) {// 当前数为素数
for (j = 2; j * i < n; j++) {
primeFlag[i * j] = 0;// 标记i * j不为素数
}
}
}
}
int main() {
/*方法2(利用素数表)*/
int primeFlag[10001];
int T = 0;
int num = 0;
int i = 0;
int count = 0;
primeArray(primeFlag, 10001);// 构建素数表
scanf("%d", &T);
while (T) {
scanf("%d", &num);
count = 0;
for (i = 2; i <= num / 2 - 1; i++) {
if (primeFlag[i] == 1 &&
primeFlag[num - i] == 1) {// 用于拆分的两数均为素数
count++;
}
}
printf("%d\n", count);
T--;
}
return 0;
}