問題描述
幸運數是波蘭數學家烏拉姆命名的,它採用與生成素數類似的「篩法」生成
首先從1開始寫出自然數1,2,3,4,5,6,…
1 就是第乙個幸運數。
我們從2這個數開始。把所有序號能被2整除的項刪除,變為:
1 _ 3 _ 5 _ 7 _ 9 ……
把它們縮緊,重新記序,為:
1 3 5 7 9 …… 這時,3為第2個幸運數,然後把所有能被3整除的序號位置的數刪去。注意,是序號位置,不是那個數本身能否被3整除!! 刪除的應該是5,11, 17, …
此時7為第3個幸運數,然後再刪去序號位置能被7整除的(19,39,…)
最後剩下的序列類似:
1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, …
輸入格式:輸入兩個正整數m n, 用空格分開 (m < n < 1000*1000)
輸出格式:程式輸出 位於m和n之間的幸運數的個數(不包含m和n)。
樣例輸入:1 20
樣例輸出:5
樣例輸入:30 69
樣例輸出:9(題目中的輸出是8,但是測試證明,確實應該是9)
---分割線---
分析:無論是題目給的提示,還是「幸運數」生成描述,都在很直接的告訴你——要用篩法
我們確實也應該從這裡出發
最開始我的想法是陣列,但是陣列種元素的缺減會導致之後的大量元素整體後移
這極有可能超時,並且陣列操作極為不便
於是想到用向量(向量中元素缺減也會導致大量元素整體後移,但是其用到了堆排序,在調整時速度遠遠快於陣列),反正既然有現成的資料結構,為什麼你還要去自己寫呢?
最後說一下我的解題思路
首先,建立乙個向量v,然後利用迴圈,將輸入資料n作為向量中的上限(即1-n)將其整體納入v中。
接著,建立乙個最外層while迴圈(退出條件為當前取出的幸運數大於向量長度)
而在此迴圈中的內容則為乙個永真迴圈(目的是將當前向量進行乙個篩選,選出每一次從向量頭到向量尾中,應該被捨棄掉的那些數)
注意:這個永真迴圈中的具體實現方式是利用乙個錯位的過程(錯位是指將應該保留下來的數字跳過,而那些該移除的數字則被刪除掉)來控制向量中資料的留與刪。
在這些while迴圈中的最裡層,我定義了乙個指標來掃瞄向量,當這個指標越界(即p>v.size())就會直接goto到迴圈外(具體見**)。
當內部兩個迴圈都結束之後,我們的工作有兩部分:
1.更新k的值(k表示了第pos+1個幸運數)
2.更新p指標為0
這樣,最後在main函式中,我就可以通過乙個迴圈來檢測出當前範圍中的幸運數個數了(需要注意的是:由於在前面的篩法中我已經限制了最大值的閾值,那麼在這裡求幸運數個數時,我僅僅需要找到最小值的位置就行了)
廢話不多說,下面直接上本題的完整**:
---分割線---
#include
#include
using
namespace std;
int pos=
1,m,n;
vector<
int> v;
void
generate()
v.erase
(v.begin()
+p);
} lable: k=v[pos++];
p=0;
}}intmain()
cout
}
藍橋杯 歷屆試題 幸運數
時間限制 1sec 記憶體限制 128mb 提交 39 解決 20 題目描述 幸運數是波蘭數學家烏拉姆命名的。它採用與生成素數類似的 篩法 生成 首先從1開始寫出自然數1,2,3,4,5,6,1 就是第乙個幸運數。我們從2這個數開始。把所有序號能被2整除的項刪除,變為 1 3 5 7 9 把它們縮緊...
藍橋杯 試題 歷屆試題 幸運數
題目鏈結 資源限制 時間限制 1.0s 記憶體限制 256.0mb 問題描述 幸運數是波蘭數學家烏拉姆命名的。它採用與生成素數類似的 篩法 生成 首先從1開始寫出自然數1,2,3,4,5,6,1 就是第乙個幸運數。我們從2這個數開始。把所有序號能被2整除的項刪除,變為 1 3 5 7 9 把它們縮緊...
藍橋杯 歷屆試題 幸運數 dfs
題目 問題描述 幸運數是波蘭數學家烏拉姆命名的。它採用與生成素數類似的 篩法 生成 首先從1開始寫出自然數1,2,3,4,5,6,1 就是第乙個幸運數。我們從2這個數開始。把所有序號能被2整除的項刪除,變為 1 3 5 7 9 把它們縮緊,重新記序,為 1 3 5 7 9 這時,3為第2個幸運數,然...