問題描述
幸運數是波蘭數學家烏拉姆命名的。它採用與生成素數類似的“篩法”生成。
首先從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
1 20
樣例輸出1
5
樣例輸入2
30 69
樣例輸出2
8
/*
思路:求幸運數區間的個數,其實難度並不難,直接暴力就行,正所謂暴力藍橋杯
我們直接直接計算,1到n的數字即可,然後我們開始篩選,因爲我們記錄的數字直接從第二次篩選結束的,所以我們直接從第三遍篩選開始即可。
每次要除的數字,是上一個幸運數,切記這一條!(本人開始,審題不清,以爲是質數,結果,此處略去罵人十萬字)
記錄下要去除數字的下標
前移即可!
最後輸出。
切記:篩選每次除的數字都是上一個幸運數
注意區間,不包含
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int m, n;
int len = 0;
int main()
{
scanf("%d %d", &m, &n);
vector <int> vc(n);
//下標從1開始
for (int i = 1; i < n; i++) vc[i] = 2 * i - 1;//記錄下第2個幸運數產生後的結果即可,節約運算
int divided = 2;
len = n;
for (int select = 3; ; ++select)
{
divided = vc[select-1];//除數是上一個幸運數
int num = 1;
for (int i = 1; i < len; i++)
if (i%divided != 0)
vc[num++] = vc[i];//vc重新賦值,覆蓋
len = num;//長度記錄
if (vc[select] > n) break;
}
int count = 0;
for (int i = 1; i < n; i++)
{
if (vc[i] >= n) break;
if (vc[i] < n && vc[i] > m) {
++count;
}
}
printf("%d", count);
return 0;
}