H106OJ_第二次练习_幸运数:
提示:本文章为课程任务(学习记录)
本文章为课程第二次练习习题记录,仅供参考。
问题描述
题目:
幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成。
首先从1开始写出自然数
1 就是第一个幸运数。
我们从2这个数开始。把所有序号能被2整除的项删除,变为:
把它们缩紧,重新记序,为:
这时,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作为第一个幸运数,但是是用2处理的。利用2将数列处理完毕后,3才变成第二个幸运数,后续就正常了。所以,先将利用2处理好的数列这种特殊先处理出来,然后用循环进行常规处理。
- 在常规处理中,仅需要一个数组就可以完成。因为对于每一个新的幸运数,其一定大于上一个幸运数序列的前面的下标,故而前面的数据不会被覆盖,且后面的数据不会出错。
- 在循环中利用变量len统计新的幸运数队列的长度,然后调节for循环次数即可。
- 其实幸运数队列很长,但是只需要求到n即可,然后再这个序列中找符合要求的数字(位于m和n之间)个数。
代码:
#include<iostream>
using namespace std;
const int N = 1e6 + 30;
int n, m, cnt;
int a[N], b[N];
int main()
{
cin >> n >> m;
int len = 0, pos = 0;
for(int i = 1; i <= m; i ++) a[++ len] = i;
for(int i = 1; i <= len; i ++)
if(i % a[2] != 0)
b[++ pos] = a[i];
len = 0;
for(int i = 2; i <= pos; i ++)
{
int idx = b[i];
for(int j = 1; j <= pos; j ++)
if(j % idx != 0)
b[++ len] = b[j];
pos = len;
len = 0;
}
for(int i = 1; i <= pos; i ++)
if(b[i] > n && b[i] < m)
cnt ++;
cout << cnt;
return 0;
}
最开始看到这个题的时候有一些误解,写出来以防读者误解(应该不会)。题目中说找出m和n中的幸运数,最开始以为是利用m为第一个幸运数,求出新的序列。统计个数。后来才读懂,幸运数队列是固定的,只是需要求到一定个数(本题至输入范围n)。再找到大于m小于n的即可。
Over,Bye~ 2022.03.22