本文仅供参考学习使用,谢谢
问题描述:
Alice和Bob来到古老的金字塔,发现古代法老留下的两个数a和b(a<b),传说如果能够在机关启动前 正确数出两个数字间 1 出现的次数,就可以得到法老的权杖。机会只有一次,你可以帮助他们么?(一个一个数肯定是来不及的。。。)
- 输入:
a,b两个数
- 输出:
两个数之间1出现的次数
思路分析:
除了0以外所有数字的出现次数都是这样计算,零不可以考虑最高位为0
- 本题的思想是从最低位开始求1出现的次数。然后把所有位1出现的次数相加。
eg:n=12345,( n=abcde ) 例如要求百位为1的数字的个数。
一共分两步走。先求0~12299 中百位 为1的数字。再求12300~12345中百位为1的数字。
0~12299 中百位为1的形式如下: ab 1 cd ,ab可取得组合为0~(ab-1)一共ab种,
对于本例即 在百位的前半部分 可取(00,01,02,03……11),即一共有ab=n/(exp10)种取法,后半段可取的范围是(0,1,2,……99)一共exp种,其中exp代表当前位,此时求的是百位,因此exp=100. 所以在第一部分中 百位出现1的情况
即为 n/(exp10) * (exp).
对于12300~12345中的部分。先确定百位上的数字是否为1,此时高位只能取ab.对于此案例只能取12.
- 若百位为1. 则出现的数字为 00~de 共(ef+1)种。
- 若百位大于1.则一共可取00~99 共exp种。
- 若百位为0,没有数字满足条件。
测试数据:
- 数据1:
8
- 结果1:
13
- 数据2:
428 1576
- 结果2:
902
代码
#include <stdio.h>
int workout(int n){
if(n<=0)
return 0;
int e = 1;
int ans = 0;
while(n/e){// 求每一位上出现1 的数字的个数。 再把所有位出现1的个数相加,即可1出现的次数
// n/(e*10)为对应位左边的取值情况,e为对应位右边的取值情况(0~-1)共e中取法
ans = ans+n/(e*10)*e;
if(n%(e*10)/e >1)//对应位> 1 的情况下,小于对应位的数为0~e
ans = ans + e;
else if(n%(e*10)/e ==1)//对应位== 1的情况下,小于对应位的数为0~ n%e
ans = ans +n%e+1;
e = e*10;
}
return ans;
}
int main(int argc, const char * argv[]) {
int a=0,b=0,end=0;
scanf("%d%d",&a,&b);
end=workout(b)-workout(a);
printf("%d\n",end);
return 0;
}