练习4-11 统计素数并求和 (20 分)

浙大版《C语言程序设计(第3版)》题目集

  • 练习4-11 统计素数并求和 (20 分)
  • 二、题解
  • c代码

练习4-11 统计素数并求和 (20 分)

本题要求统计给定整数M和N区间内素数的个数并对它们求和。

输入格式:
输入在一行中给出两个正整数M和N(1≤M≤N≤500)。

输出格式:
在一行中顺序输出M和N区间内素数的个数以及它们的和,数字间以空格分隔。

输入样例1:

10 31

输出样例1:

7 143

二、题解

这题数据量很小,暴力即可, 也可用筛法。

朴素筛法:
2 3 4 5 6 7 8 9 10 11 12
把所有数的倍数筛掉,如把2的倍数筛掉,剩下2 3 5 7 9 11, 把3的倍数筛掉,剩下2 3 4 7 11,把4的倍数筛掉,以此类推。时间复杂度为O(log n);
如果一个数P没有被筛掉,说明2 ~ (P - 1)没有一个数是P的约数,P是一个素数。

埃氏筛法:每一个合数都可以被分解为质因子相乘,如30 = 2 * 3 * 5;所以我们只需要用质因子来筛去倍数就可以了。相较于朴素筛法提高了时间效率。时间复杂度为O(log log n);

欧拉筛(线性筛):
无论是朴素筛法还是埃氏筛法都有一些数被重复筛选,降低了时间效率。因为每个合数只有一个最小质因子,若只使用他的最小质因子来进行筛选就可以避免重复筛选的现象。用一个数组来维护一个确定的素数列,从小到大去枚举素数。

st[i * primes[j]] = 1;

因为我们是从小到大去枚举质数的,所以 i * primes[j] 一定会被他的最小质因数primes[j]筛去。

if(i % primes[j] == 0)  break;

i % primes[j] == 0时,即i = primes[j] * x,若此时不去break,则下一个数z = i * primes[j + 1] = primes[j] * x * primes[j + 1]primes[j + 1]并不是z的最小质因子,会被重复筛选。举个例子,i = 6 = 2 * 3,则下一个数 z = i * 3 = 2 * 3 * 3,会被2 * 93 * 6重复筛去。

c代码

#include            

int N = 510;
int primes[510], st[510];
int cnt = 0;

//朴素筛法
void P() {
    for (int i = 2; i <= N; i++) {
    	if(!st[i])  primes[cnt++] = i;
        for (int j = i + i; j <= N; j += i) 
            st[j] = 1;
    }
}

//埃氏筛法
void P() {
    for (int i = 2; i <= 510; i++) {
        if(!st[i]) {
            primes[cnt++] = i;
            for (int j = i + i; j < N; j += i) 
                st[j] = 1;
        }
    }
}

//欧拉筛
void P() {
	for (int i = 2; i < N; i++) {
		if(!st[i])  primes[cnt++] = i;
		for (int j = 0; j < cnt && primes[j] * i < N ; j++) {
			st[i * primes[j]] = 1;
			if(i % primes[j] == 0)  break;
		}
	}
}

int main() {
    P();
    int m, n, sum = 0, cnt = 0;
    scanf("%d%d", &m, &n);
    
    int ans = 0;
	for (int i = 0; primes[i] <= n; i++) {
		if(primes[i] >= m && primes[i] <= n) {
            sum += primes[i];
            ans++;
        }
	}
    printf("%d %d\n", ans, sum);
    
    return 0;
}

你可能感兴趣的:(算法,c语言,c算法,素数筛,PTA)