2022.3.23 14:24 洛谷P5723

这篇博客展示了如何使用C和C++编程语言,以及Python,实现欧拉筛法来找寻指定范围内的素数。通过比较原始的筛选方法和优化后的算法,展示了效率提升的过程。文章提供了详细的代码解释,帮助读者理解每一步的逻辑,并给出了运行代码时应监控的关键变量变化,以辅助理解。
摘要由CSDN通过智能技术生成

C:(一开始自己写的,40分)

#include <stdio.h>


int main()
{
	int n, biao = 1;

	int a[10001];

	scanf("%d", &n);

	int j = 0,k = 0;

	for (int i = 2; i <= n - 1, k <= n; i++)
	{
		if (((i % 2 != 0) && (i % 3 != 0) && (i % 5 != 0) && (i % 7 != 0)) || i == 2 ||i == 3 || i == 5 || i == 7)
		{
			if ((k += i) > n)
			{
				break;
			}

			a[++j] = i;

			printf("%d\n", i);
		}
	}

	printf("%d", j);

	return 0;
}

C:(研究过相关知识改良后,100分)

#include <stdio.h>


int n;

bool shai(int a)
{
	for (int i = 2; i * i <= a; i++)
	{
		if (a % i == 0)
		{
			return 0;
		}
	}

	return 1;
}


int main()
{
	int a[10001];

	scanf("%d", &n);

	int j = 0,k = 0;

	for (int i = 2; i <= n - 1, k <= n; i++)
	{
		if (shai(i))
		{
			if ((k += i) > n)
			{
				break;
			}

			a[++j] = i;

			printf("%d\n", i);
		}
	}

	printf("%d", j);

	return 0;
}

C++:(100分)(学习欧拉筛后用欧拉筛法)

#include <stdio.h>


#define Max 100010  //这个最好大一些,不然我试过如果是10001的话可能会RE


bool num[Max] = { 0 };  //创建一个  有Max个元素  每个元素为bool类型  每一个元素默认为0  的数组

//创建这个数组的目的:
//通过下标间接遍历所有数( 下标=0是不要的 ),并通过 算法 将 下标中 不是素数的元素变成1,把是素数的数字放入 数组Prime 内

//效果大致如下,经过算法前:
//          num = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .......0};
//              下标: 1  2  3  4  5  6  7  8  9     100010
//
//
//              经过算法后:
//          num = {0, 1, 0, 0, 1, 0, 1, 0, 1, 1 .......0};
//              下标: 1  2  3  4  5  6  7  8  9     100010
//
//上面经过算法后  如果 数组内元素为0,就表示这 不是一个众数  (即素数)
//                如果 数组内元素为1,就表示这   是一个众数  (即不是素数)


int Prime[Max];  //创建一个  有Max个元素  每个元素为int类型  的数组
//作用:
//用于存放 在一定范围 筛选过后得到的素数
//最后 输出(打印)的是这个数组内的内容


int koudai;  //存放 一开始输入的 口袋的承重量


int b = 0;  //用来表示 数组Prime 中 空着位置的下标
            //存放第一个素数时,b = 1,随后b++
            //存放第二个素数时,b = 2,随后b++.......以此类推
            //同理因为是全局变量,也可用于 得知 数组Prime内 存放了几个素数
            //当运行到最后时,可用于得知 “口袋最多能装下的质数个数”


int c = 0;  //用于应对本题要求—“口袋的负载量就是口袋里的所有数字之和”
            //c 为 当前的 所有素数的和


void GetAllPrime(int koudai);  //声明函数


int main()
{
	scanf("%d", &koudai);  //输入

	GetAllPrime(koudai);  //算法 函数

	printf("%d", b);  //打印  “口袋最多能装下的质数个数”

	return 0;
}


/*
核心概念: 倍数 X 一个素数 = 一个众数
 
 也就是说,可以通过 上面核心概念  来“筛”(干)掉  总数,只保留素数
*/
void GetAllPrime(int koudai)  //算法  函数
{
	num[1] = 1;  //特例,表示1是一个众数


	//刚刚处理了特例,要从2开始遍历
	//这里的 i 主要用于充当 遍历数组num 的下标。
	//因为“口袋的承重量有限”,所以i <= koudai
	//同时 i 也用于充当 一个 “倍数” 的角色
	for (int i = 2; i <= koudai; i++)
	{
		if (!(num[i]))  //判断,如果 !(非)  (一个素数)  ,就执行下面{}内的内容
		{
			if ((c += i) > koudai)  //判断 当前的 所有素数的和 是否大于 口袋的承重量
			{
				break;  //跳出 最大的for循环
			}

			Prime[++b] = i;  //b先自增,然后把 当前i的值 赋给 对应下标的数组Prime

			printf("%d\n", Prime[b]);  //打印
		}


		for (int j = 1; j <= b && i * Prime[j] <= koudai; j++)  //这里的 j 主要用于充当 遍历数组Prime 的下标
		{
			num[i * Prime[j]] = 1;  //最关键的部分,倍数(i) * 一个素数(Prime[j]),那么相乘计算后得到的 数组num的下标 是一个众数,让这个众数对应的元素变成1(筛掉)

			if (i % Prime[j] == 0)  //判断,如果 i 是 数组Prime 内其中一个素数的倍数,就跳出for循环
			{
				break;
			}
		}
	}
}

其实文字可能真的很难描述清楚,建议的是F10和F11开逐句过,然后开三个及以上的监视窗口

一个用于看num的变化

一个用于看Prime的变化

还有一个看i, j, c等参数

然后自己一行一行推一小遍,慢慢理解

这是我当时自己写的图,可以参考

python:(欧拉筛,100分)

koudai = int(input(""))

def shai(koudai):
    c = 0

    b = 0

    num = [0 for i in range(koudai + 1)]  # 使用列表推导,创建一个有n + 1个元素的列表,并把每个元素初始化成0

    Prime = []  # 创建一个空列表,用于后续添加 经过算法得到的 素数

    for i in range(2, koudai + 1):
        if num[i] == 0:

            if (c + i) > koudai:
                break;

            Prime.append(i)

            c = c + i

            print(f"{Prime[b]}")

            b = b + 1

        for j in Prime:
            if i * j > koudai:
                break;

            num[i * j] = 1

            if i % j == 0:
                break;

    return Prime, len(Prime)

Prime, b = shai(koudai)

print(b)

欢迎各位大佬斧正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值