1-1 统计数字问题
问题描述: 一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编辑,每个页码不含多余的前导数字0。例如,第6页用数字6表示而不是06或006等。数字计数问题要求对给定书的总页码n,计算书的全部页码分别用到多少次数字0、1、2、…、9。

算法设计: 给定表示书的总页码的十进制整数$n(1  \leq n \leq 10^9)$,计算书的全部页码中分别用到多少次数字0、1、2、…、9。

数据输入: 输入数据由文件名为 input.txt 的文本文件提供。每个文件只有1行,给出表示书的总页码的整数n

结果输出: 将计算结果输出到文件 output.txt。输出文件共10行,在第k行(k=1,2,…,10)输出页码中用到数字k−1 的次数。

#include<iostream>
#include<cmath>
using namespace std;

int n;//页码数
int a[10]={0};//统计数字个数

//method 1: 逐个数字统计
// void count(int x){//统计数字个数
//     int num=x;
//     while(num>0){
//         a[num%10]++;
//         num/=10;
//     }
// }
//method 2:递归方式
int countNum(int n){//计算所有n位数中各数个数
    if(n==0){
        return 0;
    }
    return n*(int)pow(10,n-1);
}
int getDigitCount(int num){//获取数字位数
    int count=0;
    count=(int)log10(num)+1;
    return count;
}
void count(int n,int digitCount){//开始递归处理,从高位到低位,n为待统计数字,digitCount为数字位数
    if(digitCount==1){//如果数字位数为1,则直接统计数字个数
        for(int i=0;i<=n;i++){
            a[i]++;
        }
        return;
    }
    int highDigit=n/(int)pow(10,digitCount-1);//获取高位数字,表示由几组digitCount-1位数字组成
    int rest=n%(int)pow(10,digitCount-1);//获取剩余数字,用于之后的递归处理
    for(int i=0;i<=9;i++){//处理digitCount-1位
        a[i]+=highDigit*countNum(digitCount-1);
    }
    for(int i=0;i<highDigit;i++){//处理最高位,前highDigit-1位由digitCount-1位数字组成,最后一位由rest+1个数字组成
        a[i]+=(int)pow(10,digitCount-1);
    }
    a[highDigit]+=rest+1;
    count(rest,digitCount-1);//递归处理剩余数字
}

void subZero(int digitCount){//处理多出来的0    
    for(int i=0;i<digitCount;i++){ 
        a[0]-=(int)pow(10,i); 
    } 
} 
int main(){ 
    cin>>n;
    //method 1
    // for (int i=1;i<=n;i++){
    //     count(i);
    // }
        
    //method 2
    int digitCount=getDigitCount(n);
    count(n,digitCount);
    subZero(digitCount);

    for (int i=0;i<10;i++){
        cout<<i<<" "<<a[i]<<endl;
    }
}