题目作者:张彤彧 浙江大学
本题要求统计给定整数M和N区间内素数的个数并对它们求和。
输入格式:
输入在一行中给出两个正整数M和N(1≤M≤N≤500)。
输出格式:
在一行中顺序输出M和N区间内素数的个数以及它们的和,数字间以空格分隔。
输入样例:
10 31
输出样例:
7 143
思路1:这里是要统计[M,N]闭区间内所有素数的个数和它们的和。我们用两层循环,外层循环枚举出所有正整数i,M<=i<=N;用里层循环判断i是不是素数,若是素数就给计个数加1,和加i;若不是素数,就继续外层循环。
要判断出一个正整数是不是素数,这就是素数判定问题。根据素数的定义,一个大于等于2的正整数p,如果它只能被1和p本身整除,那么p是素数。于是我们用最原始的办法,用循环枚举出所有的正整数j,2<=j<=p-1;若某一个j能整除p,即p%j==0, 那么我们就可以标记p为合数,然后跳出循环(因为后面的遍历是没有意义的);若直到循环结束都p都没有被标记为合数,说明p确实没有1和p本身以外的其他因子,即p是素数。当然这里可以做一个简单的优化,可以不用枚举2到p-1之间的所有正整数,只需要枚举2到sqrt(p)之间的所有正整数即可。
注意:对1要单独处理,显然1也是只能被1和它本身整除的正整数,所以如果遇到1,我们不要用循环去判断它,直接跳过。在一个循环里,要跳过循环体后面所有的代码,并执行下一轮循环,用continue语句。
代码1:
#include <stdio.h>
#include <math.h>
int main () {
int M,N,i,j,cnt=0,sum=0,flag = 1;
scanf("%d%d", &M, &N);
for (i = M; i <= N; i++) {
flag = 1;
if (i == 1) continue; // 注意,这里对i==1的情况要单独处理
for (j = 2; j <= sqrt(i); j++) {
if (i%j == 0) {
flag = 0;
break;
}
}
if (flag) {
cnt++;
sum += i;
}
}
printf("%d %d", cnt, sum);
return 0;
}
我们还可以把判定素数的代码封装成一个函数,得到如下的代码:
代码2:
#include <stdio.h>
int isPrime (int P) { //定义一个函数,用来判断一个数P是不是素数,是返回1,不是返回0
int i, flag = 1;
for (i = 2; i <= sqrt(P); i++) {
if (P%i == 0) {
flag = 0;
break;
}
}
return (P <= 1) ? 0 : flag;
}
int main () {
int i,M,N,cnt=0,sum=0;
scanf("%d%d", &M, &N);
for (i = M; i <= N; i++) {
if(isPrime(i)) {
cnt++;
sum+=i;
}
}
printf("%d %d", cnt, sum);
}