Primzahlsiebmethode (ausführliche Erläuterung des Angström-Siebs und des linearen Siebs)

Der einfachste Weg, Primzahlen zu finden, besteht natürlich darin, sie einzeln zu durchlaufen. Wir durchlaufen jede Zahl der Reihe nach und beurteilen dann, ob es sich um eine Primzahl handelt oder nicht. Der Kern des Problems liegt also wieder in der Beurteilung von Primzahlen. Wie kann man also beurteilen, ob eine Zahl eine Primzahl ist?

Es gibt nur eine Eigenschaft einer Primzahl, das heißt, es gibt nur zwei Faktoren von 1 und sich selbst , und wir können diese Eigenschaft nur zur Beurteilung einer Primzahl verwenden. Man kann sich also vorstellen, dass wir, wenn wir beurteilen wollen, ob n eine Primzahl ist, von 2 nach n-1 gehen können. Wenn keine der n-1 Zahlen n teilen kann, bedeutet dies, dass n eine Primzahl ist. Ich erinnere mich richtig, dass es in den Übungen der C-Sprache vorkam. Kurz gesagt, es ist sehr einfach und man kann sagen, dass es sich um den einfachsten Algorithmus handelt.

Angström-Siebmethode

Der Eratosthenes-Algorithmus, den wir heute vorstellen werden, ist eine von ihm erfundene Methode zum Screening von Primzahlen. Der Einfachheit halber nennen wir ihn im Allgemeinen das Escherichia-Sieb oder das Sieb . Die Idee der Escherichia-Siebmethode ist sehr einfach: Sie verwendet die gescreenten Primzahlen, um alle Zahlen zu filtern, die durch sie teilbar sind. Diese Primzahlen sind wie ein Sieb zum Filtern natürlicher Zahlen, und die nach dem Sieben verbleibenden Zahlen sind natürlich Zahlen, die nicht durch die vorherigen Primzahlen teilbar sind. Gemäß der Definition von Primzahlen sind diese verbleibenden Zahlen ebenfalls Primzahlen.

Wenn wir beispielsweise alle Primzahlen innerhalb von 100 herausfiltern möchten, wissen wir, dass 2 die kleinste Primzahl ist, können wir 2 verwenden, um zuerst alle geraden Zahlen herauszufiltern. Gehen Sie dann zurück zu 3, 3 ist die erste Zahl, die nach dem Sieben durch 2 übrig bleibt, und es ist auch eine Primzahl. Wir verwenden dann 3, um alle Zahlen herauszusieben, die durch 3 teilbar sind. Nach dem Sieben setzen wir die Traversierung rückwärts fort. Die erste gefundene Zahl ist 7, also ist 7 auch eine Primzahl. Wir wiederholen den obigen Vorgang, bis die Traversierung endet. Am Ende haben wir alle Primzahlen bis 100.

Wenn Sie es immer noch nicht ganz verstanden haben, können Sie sich die folgende Animation ansehen, die den gesamten Vorgang sehr anschaulich wiedergibt.

Zeitkomplexität ist 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;
}

Euler-Sieb

Die Euler-Siebmethode wird auch als lineare Siebmethode bezeichnet, mit der die Primzahlen in 1 ~ n in O (n) linearer Zeit gesiebt werden können.

Beispielsweise kann die zusammengesetzte Zahl 6 durch die Primzahlen 2 und 3 durchgestrichen werden. Zu diesem Zeitpunkt müssen wir nur die kleinste Primzahl deutlich durchstreichen.

#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;
}

Ich denke du magst

Origin blog.csdn.net/zhi6fui/article/details/128633372
Empfohlen
Rangfolge