原题链接:题目506 - ACM在线评测系统
描述:
Mostrp是个爱干净的好少年。 有一次去澡堂洗澡时发现 澡堂的澡柜编号中没有出现过数字‘4’。 Mostrp 感到很好奇。可能是因为在澡堂老板眼里。数字‘4’是十分不吉利的。现在Mostrp知道澡柜的最大的编号N,你能帮他算出澡堂一共有多少澡柜吗?
输入:
有多组数据,每行输入一个N。
( 1 <= N <= 50000 )
输出:
输出澡柜的个数,输出占一行。
样例输入:
3
41
399
50000
样例输出:
3
36
323
26244
解题思路:
最多N个澡柜有编号,遍历N以内的正整数,如果某编号在某位有4,就减去这个编号。
注意事项:
有的算法虽然快,能覆盖大部分用例,但是仍有缺陷,有待优化。
参考代码:
#include<stdio.h> int main(){ int i,n,c,N; while(~scanf("%d",&N)){ c=N;//最多有N个澡柜 for(i=1;i<N;i++){//遍历N以内的正整数 n=i; while(n){ if(4==n%10){//某数在某位有4 c--;//没有这个澡柜 break; } n/=10;//寻找该数的更高位 } } printf("%d\n",c); } return 0; }
下面还有递归的方法,以及DFS(Depth-First-Search)深度优先搜索算法,当N=41时结果是35,与答案36不相符。
/* 查看代码---运行号:2490709----结果:Accepted 运行时间:2018-05-22 11:22:57 | 运行人:ACM_李朝强 */ #include<stdio.h> int a[10]; int dp[10]; int dfs(int pos,int last){ int len,ans; if(!pos) return 1; if(!last&&dp[pos]) return dp[pos]; len=last?a[pos]:9; ans=0; for(int i=len;i>=0;i--) ans+=i==4?0:dfs(pos-1,last&&i==len); if(!last) dp[pos]=ans; return ans; } int solve(int n){ int len=0; while(n) a[++len]=n%10,n/=10; return dfs(len,1)-1; } int main(){ int n; while(scanf("%d",&n)!=EOF) printf("%d\n",solve(n)); return 0; }
还有更快的,几乎找到了公式,加了注释后如下:
/* 查看代码---运行号:371556----结果:Accepted 运行时间:2013-03-31 16:08:44 | 运行人:王力伟 */ #include<stdio.h> int main(){ int n,s; while(~scanf("%d",&n)){//n作为澡柜编号,每位不可能包含4 s=0;//s表示不存在的澡柜个数 if(n>4) s=(n+6)/10;//当n属于[5,39],s属于[1,4] //当n为41,不存在的编号为4,14,24,34,40,只有5个,答案是13个,答案错误 /*当n为399,不存在的编号为 4,14,24,34,40,41,42,43,44,45,46,47,48,49,54,64,74,84,94, 104,114,124,134,140,141,142,143,144,145,146,147,148,149,154,164,174,184,194, 204,214,224,234,240,241,242,243,244,245,246,247,248,249,254,264,274,284,294, 304,314,324,334,340,341,342,343,344,345,346,347,348,349,354,364,374,384,394 ,有76个,答案正确*/ if(n>40) s+=(n+60)/100*9; if(n>400) s+=(n+600)/1000*81; if(n>4000) s+=(n+6000)/10000*729; if(n>40000) s+=(n+60000)/100000*729*9; printf("%d\n",n-s); } return 0; }
这之后,找到了可接受的方法,用空间换效率,a[max]保存从1到max-10的编号,用例再多也不怕时间超限:
/* 查看代码---运行号:2456688----结果:Accepted 运行时间:2018-04-16 21:57:51 | 运行人:ycxy06104 */ #include<stdio.h> #define max 50010 int a[max]; int cmp(int n) { while(n) { if(n%10==4) return 1; n=n/10; } return 0; } int main() { int n; for(int i=1;i<=50000;i++) { if(cmp(i)) a[i]=a[i-1]; else a[i]=a[i-1]+1; } while(scanf("%d",&n)!=EOF) printf("%d\n",a[n]); return 0; }
0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复