藍橋杯 歷屆試題 幸運數(向量篩)

2021-09-26 15:36:18 字數 1739 閱讀 5331

問題描述

幸運數是波蘭數學家烏拉姆命名的,它採用與生成素數類似的「篩法」生成

首先從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個幸運數,然...