【問題描述】
2023年,德國數學家哥德**(goldbach)提出了著名的哥德**猜想(goldbach conjecture):任何乙個不小於4的偶數可以表示為兩個素數之和。這個猜想至今都沒有完全被證明是正確的。
但是,對於乙個大於或等於5的奇數,有的可以表示成兩個素數之和,有的則不能。給定乙個大於或等於5的奇數,判斷是否能分解成兩個素數之和。
【輸入形式】
輸入中包含多個測試資料,每個測試資料佔一行,為乙個正整數m,m為奇數,且不小於5,不大於32767。
【輸出形式】
對每個測試資料,如果m能分解成兩個素數之和,輸出yes,否則輸出no。
【樣例輸入】
【樣例輸出】
yesyes
yesno
題意很簡單,就是判斷乙個數能不能拆分成兩個素數。
輸入型別屬於一直輸入到檔案尾,所以用while(cin>>n)的方法進行輸入。
先看暴力演算法,時間複雜度o(n^3)
(一看這複雜度就知道要gg)
#include
using
namespace std;
int n;
bool
judge
(int x)
//判斷是否為素數
return
true;}
bool
check
(int a)
return
false;}
intmain()
}
顯然,暴力是不給讓過的(好歹是一道演算法題,不會給你打暴力的機會的)
所以要請同學們收起上學期一言不合就打暴力的思維方式。
優化1 數論知識
數學蒟蒻就不好意思來balabala證明什麼了,就直接拋結論:
如果將乙個奇數分為2和另乙個數,如果這兩個數都為素數,那麼這個數可以被分為兩個素數之合,反之不能
說白了就是只判斷n-2是不是素數
用這個方式可以省去一層迴圈,複雜度優化到o(n^2)
#include
using
namespace std;
int n;
bool
judge
(int x)
//判斷是否為素數
優化一層迴圈後就成功擠進1s內了
那麼問題來了,能不能再優化一點呢?
優化2 篩質數+打表
先解釋一下打表,打表是一類演算法的統稱,大致為在程式正式執行前將一些資料提前算出來,比如這道題,測試資料最大值僅有32767,我們就可以將32800之前的所有素數先算出來。
其次是篩質數,這是這道題的一種打表方式。如果用常規判斷質素的方式,可能表還沒打完程式就被切了。
篩質數就是列舉某數的倍數,將除了1之外所有數的倍數篩掉,剩下的就全是質數了。
比如,計算1到20的質數
篩掉2的倍數 4,6,8,10,12,14,16,18,20
篩掉3的倍數 6,9,12,15,18
篩掉5的倍數10, 15
篩掉7的倍數 7,14
。。。。。。。。。。
篩到最後就只剩下 1(捨去),2,3,5,7,11,13,17,19.
這樣就能算出素數。
如果不怕麻煩的話甚至可以把這些素數寫進**,這才是真正的打表
時間複雜度o(n)
蕪湖起飛
#include
using
namespace std;
int m;
const
int n=
32800
;int a[n]
;void
build()
//算素數 }}
bool
check
(int x)
intmain()
}
PAT乙級題解( 1007 素數對猜想
時間限制 400 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 chen,yue 讓我們定義 dn 為 dn pn 1 pn,其中 pi 是第i個素數。顯然有 d1 1 且對於n 1有 dn 是偶數。素數對猜想 認為 存在無窮多對相鄰且差為2的素數 現...
PAT 1007 素數對猜想 題解
讓我們定義d n 為 d n p n 1 p n 其中p i 是第i個素數。顯然有d 1 1,且對於n 1有d n 是偶數。素數對猜想 認為 存在無窮多對相鄰且差為2的素數 現給定任意正整數n 10 5 請計算不超過n的滿足猜想的素數對的個數。輸入在一行給出正整數n。在一行中輸出不超過n的滿足猜想的...
HDU 1282 回文數猜想(題解)
回文數猜想 乙個正整數,如果從左向右讀 稱之為正序數 和從右向左讀 稱之為倒序數 是一樣的,這樣的數就叫回文數。任取乙個正整數,如果不是回文數,將該數與他的倒序數相加,若其和不是回文數,則重複上述步驟,一直到獲得回文數為止。例如 68變成154 68 86 再變成605 154 451 最後變成11...