Метод сита простых чисел (подробное объяснение сита Ангстрема и линейного сита)

Самый простой способ найти простые числа — это, конечно, пройти по одному. Мы обходим каждое число по очереди, а затем судим, является ли оно простым числом или нет. Итак, суть проблемы сводится к оценке простых чисел: как же определить, является ли число простым?

У простого числа есть только одно свойство, то есть есть только два делителя 1 и самого себя , и мы можем использовать это свойство только для оценки простого числа. Таким образом, можно представить, что если мы хотим определить, является ли n простым числом, мы можем перейти от 2 к n — 1. Если ни одно из чисел n — 1 не может делиться n, то n — простое число. Я правильно помню, что он появлялся в упражнениях по языку C. Короче говоря, он очень простой и можно сказать, что это простейший алгоритм.

Ситовой метод Ангстрема

Алгоритм Эратосфена, который мы собираемся представить сегодня, — это метод, который он изобрел для отбора простых чисел.Для удобства мы обычно называем его решетом Эшерихии или решетом . Идея метода сита Escherichia очень проста: использовать проверенные простые числа для фильтрации всех чисел, которые могут на него делиться. Эти простые числа подобны сито для фильтрации натуральных чисел, а числа, оставшиеся после просеивания, естественно, являются числами, которые не могут делиться на предыдущие простые числа. Согласно определению простых чисел, эти оставшиеся числа также являются простыми числами.

Например, если мы хотим отфильтровать все простые числа в пределах 100, мы знаем, что 2 — это наименьшее простое число, мы можем использовать 2, чтобы сначала отфильтровать все четные числа. Затем вернитесь к 3, 3 — это первое число, оставшееся после просеивания на 2, и оно также является простым числом. Затем мы используем 3, чтобы отсеять все числа, которые делятся на 3. После просмотра мы продолжаем обход назад. Первое встреченное число — 7, поэтому 7 также является простым числом. Мы повторяем описанный выше процесс до конца обхода. В конце у нас есть все простые числа до 100.

Если вы все еще не совсем поняли, можете посмотреть следующую анимацию, которая очень наглядно восстанавливает весь процесс.

Временная сложность равна O(nlognlongn).

#include<iostream>
using namespace std;
const int N = 1e7;
int prime[N + 1];
bool visit[N + 1];
//素数筛
//埃式筛
int E_sieve(int n) {
	int k = 0;
	for (int i = 0; i < n; i++) visit[i] = false;
	// 1.普通
	/* for (int i = 2; i <= n; i++) {
		if (!visit[i]) {
			prime[k++] = i;
			for (int j = i * 2; j <= n; j+=i) { // i的倍数筛选调
				visit[j] = true;
			}
		}
	}*/
	//2.优化 有些数可能会被多筛几遍 这样会影响时间复杂度
	for (int i = 2; i * i <= n; i++)
		if (!visit[i])
			for (int j = i * i; j <= n; j += i) visit[j] = true;
	int k = 0;
	for (int i = 2; i <= n; i++) { // i * i 前面的合数被更小的素数划掉了
		if (!visit[i]) prime[k++] = i;
	}
	return k; // 1~n中的素数
}


int main() {
	return 0;
}

Эйлерово сито

Метод решета Эйлера также называется методом линейного решета, который позволяет просеивать простые числа от 1 до n за линейное время O(n).

Например, составное число 6 можно зачеркнуть простыми числами 2 и 3. На этот раз нам нужно лишь четко вычеркнуть самое маленькое простое число.

#include<iostream>
using namespace std;
const int N = 1e7;
int prime[N + 1];
bool visit[N + 1];
//素数筛
//埃式筛
int E_sieve(int n) {
	int k = 0;
	for (int i = 0; i < n; i++) visit[i] = false;
	// 1.普通
	/* for (int i = 2; i <= n; i++) {
		if (!visit[i]) {
			prime[k++] = i;
			for (int j = i * 2; j <= n; j+=i) { // i的倍数筛选调
				visit[j] = true;
			}
		}
	}*/
	//2.优化 有些数可能会被多筛几遍 这样会影响时间复杂度
	for (int i = 2; i * i <= n; i++)
		if (!visit[i])
			for (int j = i * i; j <= n; j += i) visit[j] = true;
	int k = 0;
	for (int i = 2; i <= n; i++) { // i * i 前面的合数被更小的素数划掉了
		if (!visit[i]) prime[k++] = i;
	}
	return k; // 1~n中的素数
}
bool vis[N + 1];
int euler_sieve(int n) {
	int cnt = 0;
	memset(vis, 0, sizeof(vis));
	memset(prime, 0, sizeof(prime));

	for (int i = 2; i <= n; i++) {
		if (!vis[i]) prime[cnt++] = i;
		for (int j = 0; j < cnt; j++) {
			if (i * prime[j] > n) break; //越界的不需要了
			vis[i * prime[j]] = 1;//prime中全部的素数相乘一定式合数
			if (i % prime[j] == 0) break; //  每个合数只被最小质因子划掉 
		}
	}
	return cnt;
}
int main() {
	return 0;
}

рекомендация

отblog.csdn.net/zhi6fui/article/details/128633372