本专辑上篇: [普及练习场] 生活大爆炸版石头剪刀布
编辑
看得都爽,对吧!感谢hydro的页面和浴谷的搬运。
目录
一.读题
失踪的7
题目描述
远古的 Pascal 人也使用阿拉伯数字来进行计数,但是他们又不喜欢使用 77 ,因为他们认为 77 是一个不吉祥的数字,所以 Pascal 数字 88 其实表示的是自然数中的 77,1818 表示的是自然数中的 1616 。请计算,在正整数 nn 范围以内包含有多少个 Pascal 数字。
输入格式
第一行为正整数 tt,接下来 tt 行,每行一个正整数 nn,且保证输入 nn 的是 Pascal 数字
输出格式
对于每个正整数 nn,输出 nn 以内的 Pascal 数的个数。
输入数据 1
2 10 20
输出数据 1
9 18
提示
对于所有数据,1 \leq t \leq 100001≤t≤10000,1 \leq n \leq 2^{32}-11≤n≤232−1。
题意
计算在1到n的所有整数中有多少个不含7的数。
二 .做题
算法原理
很容易发现,
n每增加10(n≠70),含7数字个数加1个,Pascal数字增加9^1个;
n每增加100(n≠700),含7数字个数加10+9×1个,Pascal数字增加9^2个;
n每增加1000(n≠7000),含7数字个数加100+9×(10+9×1)个,Pascal数字增加9^3个;
n每增加10000(n≠70000),含7数字个数加1000+9×(100+9×(10+9×1))个,Pascal数字增加9^4个;
……
为了方便解释,将增加的个数成为基准值
算法实现
①从个位到最高位分解n。
②如果这一位数小于七,那么直接加上 它乘它那基准值(为了方便解释,将增加的个数成为基准值);如果大于七,还要在上面的基础上减去一个基准值。因为类似于700-799,700000-799999,7000-7999,这些数一个都不是Pascal数,与上述规则不符,要全部减去。
全篇代码分解讲解
输入
scanf("%d",&t);
中心
第一个while相当于for(int i=1;i<=t;i++)。
输入n后,开始模拟实现上述过程。f用来算基准值,s来统计个数。第二个while用来拆解n,自己看吧!
最后,输出。
while(t--) { long long s=0,f=1; scanf("%lld",&n); while(n!=0) { int q=n%10; if(q<7) s+=f*q; else s+=f*q-f; f*=9; n/=10; } printf("%lld\n",s); }
下次,我们将讲解:题目详情 - 楼房 - 浴谷 - HydroOJ