【数据结构】欧拉函数+欧拉筛选(快来看怎么筛选出质数)

看到的好版本

版本一:清晰明了,爱了爱了。

https://www.cnblogs.com/-citywall123/p/10066464.html

tips:欧拉筛代码得到指数的同时,还得到每个数对应的欧拉函数。

版本二:快速直接地用欧拉筛得到质数

https://blog.csdn.net/codertcm/article/details/82837259

算法简述

我们希望找到 1 - N内所有的质数。做法时标记每一个数,质数标记为0,合数标记为1。初始化每个数都是0。现在从小到大对每个数依次排查。对每个数 n n n 有两步操作:

  1. 如果标记为0,加入到质数数组。
  2. 无论 n 是不是质数,都将 n 和质数数组里的每一个数依次相乘。注意是依次。核心来了:如果相乘时发现 n 是该质数的倍数,先将它们的积标记为1,再终止第二步

第二步里标记和终止的顺序不能交换,一定先标记,再交换。不然会有一些合数该被标记却没被标记为1. 终止的做法可以减少一个合数被重复标记的次数。

证明

证明: 任一一个合数 n 都会被标记为1

合数 n 可以写成 n = m 1 ∗ m 2 , m 1 < = m 2 n = m_1 * m_2,m_1 <= m_2 n=m1m2m1<=m2.

  1. m 1 , m 2 m_1, m_2 m1,m2 都是质数,则当程序运行到 m 2 m_2 m2 轮次时, n 被标记为1。
  2. m 1 m_1 m1 是质数, m 2 m_2 m2 是合数。可以证明对于任一合数我们总能找到一组 m 1 , m 2 , 其 中 m 1 是 质 数 , m 2 是 合 数 , 且 m 1 < m 2 m_1, m_2, 其中 m_1是质数, m_2是合数,且 m_1 < m_2 m1,m2,m1m2m1<m2. 因为任一合数等于一些质数相乘,令 m 1 m_1 m1 为最小的质数, m 2 m_2 m2 为其他质数的积。则程序运行到 m 2 m_2 m2 轮次 时, n 被标记为1.

tips:每一个数可能不止被标记一次,例如 n = 3 ∗ 5 ∗ 7 ∗ 11 n = 3 * 5 * 7 * 11 n=35711, 轮次 3 ∗ 5 ∗ 7 3*5*7 357, 3 ∗ 5 ∗ 11 3*5*11 3511,时都会被标记。

代码

#include <iostream>
#include <vector>
using namespace std;

void EulerPrime(int n){
	if(n == 1){
		cout << 0;
		return;
	}
	int flag[n+1] = {};
	int prime[n+1];
	int count = 0;
	for(int i = 2; i <= n; i++){
		if(flag[i] == 0) prime[++count] = i;
		for(int j = 1; j <= count && i*prime[j] <= n; j++){
			flag[i*prime[j]] = 1;
			if(i % prime[j] == 0) break;
		}
	}
	for(int i = 1; i <= count; i++){
		cout << prime[i] << endl;
	}
	cout << count << endl;
}



int main(){
	int n;
	cin >> n;
	EulerPrime(n);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值