【一只蒟蒻的刷题历程】 【蓝桥杯】 试题 历届试题 幸运数(模拟 详细过程)

问题描述

幸运数是波兰数学家乌拉姆命名的。它采用与生成素数类似的“筛法”生成

首先从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

思路

看着数挺大的,但是数据应该挺水的,只用了31ms。在这里插入图片描述
ps:第一个幸运数虽然是1,但是要把2当作幸运数来进行遍历删除

模拟:先开一个数组,1代表幸运数,inf代表被删去,首先要确定当前的幸运数是什么,然后遍历,如果某个位置没有被删除,计数器c就+1,每当计数器c等于幸运数,就可以删除该位置的数组(赋值为inf)

比如样例一:1 - 20 (1为幸运数,把2当作幸运数操作)
开始 : 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

第一次: 1 inf 0 inf 0 inf 0 inf 0 inf 0 inf 0 inf 0 inf 0 inf 0 inf

(下一个幸运数就是第一个为0的数组下标值,为3)

(inf 是被删除的值,后面操作时跳过,比如第二次幸运数为3,那么第一个删除的值应该是数组下标5,因为前面有两个inf,这两个数已经被删除,所以数组下标5就是当前数组的第3个数,以此类推)

.。。。。。。。。。。。。。。。。

就这样一直下去,直到幸运数查找到了最后一个数,退出循环

代码:

#include <iostream>
#include <algorithm> 
#include <vector>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std; 
const int maxn=1e6+50;
const int inf=1<<27;   //表示被删除 
int a[maxn]={0};    //1代表幸运数
int ans=0,flag=0;  //ans记录个数 , flag判断跳出循环

int main()
{
   int n,m;
   int p=2;  //当前幸运数
   cin>>m>>n;
   
    a[1]=1;
    
    while(1)
    {
    	int c=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(a[i]!=inf)  //没有被删除
    		{
    			c++;   //计数器+1
    			if(c==p)  //(计数器等于幸运数)
    			{
    				a[i]=inf; //删除
    				c=0;   //计数器归0
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i==n) flag=1; 
			//幸运数找到最后一个位置了(后面没了)
			//此时标记flag,准备跳出循环
			if(a[i]==0)//第一个为0的数
			{
				a[i]=1;   //记为幸运数
				p=i;     //更新当前幸运数
				break;   //退出循环
			}
		}
		
		if(flag==1) break;  //跳出循环
	}
	 
	
	for(int i=m+1;i<n;i++)
	if(a[i]==1) ans++;    //记录幸运数的个数
	
	cout<<ans;

	return 0;     
}
原创文章 32 获赞 35 访问量 1524

猜你喜欢

转载自blog.csdn.net/weixin_45260385/article/details/105783950
今日推荐