传送门:蓝桥杯
题目大意:
锦囊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;
}