问题 E: 统计数字问题ytuoj

问题 E: 统计数字问题

题目描述

一本书的页码从自然数 1 开始顺序编码直到自然数 n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字 0。例如,第 6 页用数字 6 表示,而不是 06 或 006 等。数字计数问题要求对给定书的总页码 n,计算出书的全部页码中分别用到多少次数字 0, 1, 2, \dots, 9。给定表示书的总页码的10 进制整数n (1 \le n \le 10^7)。
输入
输入数据只有 1 1 1 行,给出表示书的总页码的整数 n n n
输出
输出数据共有 10 10 10 行,在第 k k k 行输出页码中用到数字 k − 1 k-1 k1 的次数, k = 1 , 2 , … , 10 k = 1, 2, \dots, 10 k=1,2,,10
输入输出样例

样例输入

11

样例输出

1
4
1
1
1
1
1
1
1
1

详解

最直观的方法,从一到n罗列,拆数,0-9计数器叠加,不过n<=10^7,时间可能超限,我觉得用数学计算也能解决,我们以238为例,依次去看每个数在每个位置上出现的次数。

  • 在个位上,8出现在 8,18,28,38,48,58,68,78,88,98,108,118,128,138,148,158,168,178,188,198,208,218,228,238,一共24次,其他小于8的数同上也是24次,而大于8的数只出现23次。

  • 在十位上,3出现在30-39,130-139,230-238,一共是20+9=29次,小于3的
    是30次,而大于3的数,有20次。

  • 在百位上,2出现39次,小于2的出现100次,大于2出现0次

  • 统计8,一共出现24+20=44次。

    不难发现,在每个位上时,都分成三部分,小于该数的和等于该数的和大于该数的。

  • 当小于时,次数为(高位+1)*对应位次:如个位,238高位为23,低位为0,次数为(23+1)*1=24。十位238高位为2,次数为(2+1)*10=30次,百位(0+1)*100=100次

  • 等于时,次数为高位对应位次+(低位+1):个位上,238高位为23,低位为0,次数为231+0+1=24。十位238高位为2,低位为8,次数为2*10+8+1=29次,百位(0)*100+38+1=39次

  • 大于时,次数为高位对应位次:个位上,238高位为23,次数为231=23。十位238高位为2,次数为2*10次,百位(0)*100=0次
    但是,0,要特殊处理,因为每一次都把0当作前导处理了
    可以写代码了(鼓掌

#include<bits/stdc++.h>
using namespace std;
int k,a[10]={0,0,0,0,0,0,0,0,0,0};//计数器
void count(){
    int len=to_string(k).length();//把k转成字符串再求其长度
    for(int i=0;i<len;i++){
        int num=(k/(int)pow(10,i))%10;//求当前数字
        int high=k/(int)pow(10,i+1);//高位
        int low=k%(int)pow(10,i);//低位
//相等时
        a[num]+=high*pow(10,i)+low+1;
//小于时     
        for(int j=0;j<num;j++){
            a[j]+=(high+1)*pow(10,i);
            
        }
//大于时
        for(int j=num+1;j<10;j++){
            a[j]+=(high)*pow(10,i);
            
        }
//0处理
        a[0]-=(int)pow(10,i);
    }
    for(int j=0;j<10;j++){
       cout<< a[j]<<endl;
    }
}
int main(){
    cin>>k;
    count();
}

—————— The end——————

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值