个人笔记:算法讲座2.1——法老的权杖(某数出现的频率)

本文仅供参考学习使用,谢谢

问题描述:

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/(exp
10) * (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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值