蓝桥杯 历届试题 幸运数 (堆+DFS)

传送门:蓝桥杯



题目大意:

求区间 [m,n] 中幸运数的个数。



锦囊2:

从左到右扫描,用一下堆来处理,堆的每项记录下要删的倍数和当前删到的值,以当前删到的值建小根堆。每次取出一个加上一次倍数再放回去。枚举每一个数,如果这个数被跳过了就枚举下一个,如果没被跳过就找到了一个幸运数,把它的两倍加入堆。2的倍数可以特别处理一下。



思路:

因为提示用堆来做,我第一反应是用优先队列来做,但是发现优先队列不能很方便的按照下标遍历……GG……


正确的姿势是配合DFS暴力模拟,先去除下标为2的倍数的数,得到所有奇数。然后在此基础上,去除下标是当前位置数 x 的倍数的数,完成之后得到所有的幸运数。统计其中位于所求区间内的数的个数即可。



代码:

#include<stdio.h>

int m,n,a[1000010];

void dfs(int dep)
{
	int cnt=dep;
	if(a[dep]>n) return;
	for(int i=dep;i<n;i++)
	{ //从当前位置往后遍历
		//如果位置 i不是 dep位置数的倍数则添加到数列中 
		if(i%a[dep]) a[cnt++]=a[i];
	}
	dfs(dep+1);
}

int main()
{
	int i,ans;			
	while(~scanf("%d%d",&m,&n))
	{
		for(i=1;i<=n;i++) a[i]=i*2-1;		
		dfs(2); //从数字 2 的位置dfs即可 
		i=1;
		ans=0;
		while(a[i]<n)
		{ //求所求区间内的数的个数 
			if(a[i++]>m) ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值