1049 Counting Ones

题目描述
解题思路:偏思维的一道题目。
对于1的位数统计,可以考虑每个位上1出现的次数。那么从1~N中1出现的个数就可以转化为每位上1出现的次数的总和。
对于某一位中,1出现的次数计算方式如下:
如:abcdefg这个数,现要统计d这个数字这一位上1出现的次数。
记d右边总共有k位
考虑三种情况:
(1) d为0,则左边可能数字出现的情况为0~abc-1 右边可能数字出现的情况为10^k。则总共出现的次数为abc * (efg+1)
(2) d为1,则左边可能数字出现的情况为0~abc-1 右边可能出现的情况为10^k 并且加上 左边出现的数字为 abc 右边出现的数字情况为0~efg。则总共出现的次数为abc*10^k + efg+1
(3)d>1,则左边可能出现的情况为0~abc,右边可能出现的情况总数为10^k,则总次数为(abc+1)*10 ^ k
疑惑点:1. 如果从0开始统计,是否会造成数字重复统计。答案是不会的,例如 0002123 与 0020123 左边是0 右边是123 结果是不一样的 正是因为所在的位不同,所以必定不可能会出现一样的数字造成重复统计。2. 当取第1位的时候,公式规律会不会不成立。答案是不会的,取第1位的时候,d不可能是0,这就使得left虽然等于0,但是带进去仍然符合要求。

#include<iostream>
using namespace std;
int main(){
    int n,k=1,res=0,left=0,right=0;
    cin>>n;
    while(n/k){
        left = n/k/10;
        right = n%k;
        int d = n/k%10;
        if(d == 0) res += left*k;
        else if(d == 1) res += left*k + right + 1;
        else res += (left+1)*k;
        k*=10;
    }
    cout<<res;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值