原题链接:蓝桥杯2013年第四届真题-幸运数
解题思路:
1.思路很简单,就是开个一维数组,模拟手算,作递增1的初始化,形如[1,2,3..n],注意理解题,因为这里只算位于m 到 n之间的幸运数个数,那算遍历数组,算到n就可以结束了。
2.我的算法中没有将删掉的数用后面的数补空位,是因为那样每一轮删除数字,都要对整个数组移位,时间复杂度太高,为O(n*n),果断超时
3.因为没有将删除的数用后位数补上,说白了就是没有更新数的的下标。解决办法很简单,就是跳过空位,用step表示数字的实际下标( 姑且叫逻辑下标比较好理解些! ),更新下标step,满足整除情况时,删掉该位置的数字,即置为0
注意事项:
这里代码看起来两重循环 ,好像时间复杂度达到了o(n^2),但稍微想想,时间复杂度实际上是小了很多,
O(n*e),由于计算中,删掉的数字的个数是都是不定的,但可以肯定e是远小于n的
参考代码:
#include<iostream>
#define maxBit 1000050
using namespace std;
int main(){
int a[maxBit],m,n,count=0,i=2,t;
cin>>m>>n; // m < n <1000000
if(n-m<=1)
{ cout<<count; return 0;} //m n之间没有数时,count为0
for(int j=1;j<=n;j++)
a[j]=j; //初始化数列
while(i<=n){
while(a[i]==0)i++;
int step=0;
t=a[i]; //a[i]有可能也会被置0,不作除数,用t保存值
for(int d=1;d<=n;d++){ //相关序号的数 置为0
if(a[d]!=0) step++; //记录逻辑下标
if(step%t==0&&step!=0) a[d]=0;
}
if(a[i]!=0) i++; //如果算完了一轮没有删除a[i],则保留,指针i后移
}
for(i=m+1;i<n;i++)
if(a[i]!=0) count++;
cout<<count;
return 0;
}0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复