洛谷p1579 +線性篩法(歐拉篩法)的個人理解

先上題目:

一般而言,對於求質數,素數,有三種方法(~~抱歉,是我只知道三種~~)

①首先!最簡單的是,對一個數從2到其平方跟,檢測是否能夠整除,均不能被整除,素數出現!

bool prime(int x)
{
    for (int j=2;j<=sqrt(x);j++)
    if (x%j==0) return false;
    return true;
}

②其次,就是埃氏篩法了,通過將已有的質數進行倍數放大,得到的數必然不是素數,然後逐個質數進行放大,最終取其補集即可!額,對了,0,1除外,這輛不是素數也不是合數。

void Prime()  
{  
    for (int i=0; i<MAXN; i++) prime[i]=1;  //先把每個數都定義爲合數
    prime[0]=prime[1]=0;  
    for (int i=2; i<MAXN; i++)  
    {  
        if (!prime[i]) continue;  
        for (int j=i*2; j<MAXN; j+=i) prime[j] = 0;  //將i的倍數標記爲合數
    }  
}

③最後,那就本次的重點了!線性篩法,亦稱歐拉篩法

void Pn() {//先把質數表做出來
	pn[0] = 2;
	for (int i = 3; i < 20000; i++) {
		bool flag=true;
		for (int j = 0; j < x; j++) {
			if (i % pn[j] == 0) {
				flag = false;
				break;//能被一個最小的素數整除,非素數
			}
			
		}
		if (flag) {
			pn[x++] = i;
		}
	}
}

分析:pn用來存取,所有已經獲取的質數,x則爲已獲取的所有質數的個數,從3開始,遍歷質數表,3不能整除任何素數,則3也是一個素數。(此處補充一個數學原理:所有的合數均存在一個最小質數因子,就像6,它的因子有1,6,2,3,而2就是它的最小質數因子

 

每次整除一個最小的質數將會跳出循環,所以每個數字,只會被最小的質數篩一次(非常重要!!核心思想!!),所以整個

算法的時間複雜度接近於o(N).

THEN!

回過來,看看題目,我只要加個搜索就好了,找到我就停。

#include <iostream>
#include <cmath>
#include <iomanip>


using namespace std;

//p1579,分析:先做出質數表,然後通過dfs來找出匹配三個質數。

int pn[20000];//用於記錄已有的素數
int x=1;//記錄素數的個數
int sum;//記錄和
int ans[3] = {0};//記錄三個加數所屬的質數位置
//int used[20000] = { 0 };//記錄該質數是否被使用過

void Pn() {//先把質數表做出來
	pn[0] = 2;
	for (int i = 3; i < 20000; i++) {
		bool flag=true;
		for (int j = 0; j < x; j++) {
			if (i % pn[j] == 0) {
				flag = false;
				break;//能被一個最小的素數整除,非素數
			}
			
		}
		if (flag) {
			pn[x++] = i;
		}
	}
}
bool flag = false;
void dfs(int count) {
	if (flag) {//已經找到則無需再找
		return;
	}
	if (count == 3) {//到了個數就判斷是否滿足
		if (pn[ans[0]]+pn[ans[1]]+pn[ans[2]] == sum) {
			flag = true;
			cout << pn[ans[0]] << " " << pn[ans[1]] << " " << pn[ans[2]];
		}
		return;
	}
	for (int i = 0; i < x; i++) {
		/*if (used[i] == 0) {
			used[i] = 1;
			ans[count] = i;
			dfs(count + 1);
			used[i] = 0;
		}*/
		ans[count] = i;
		dfs(count + 1);
	}
}


int main() {
	Pn();
	/*for (int i = 0; i < x; i++)
	{
		cout << pn[i] << " ";
	}*/
	
	cin >> sum;
	dfs(0);

}

原本以爲用dfs,後來發現元素可以重用,簡單搜索即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章