【3006】统计数字

统计数字

Time Limit: 3 second
Memory Limit: 2 MB

【问题描述】

    一本书的页数为N,页码从1开始编起,请你求出全部页码中,用了多少个0、1、2、3、4、5、6、7、8、9。其中每个页码不含多余的0,如N=123时,第5页不是005,只是5,第12页不是012,只是12。

【输入】

    输入文件仅一行,一个正整数N(N≤109),表示总的页码数。

【输出】

    输出文件十行,第K行为数字k-1的个数,即第一行为数字0的个数,第二行为数字1的个数,第三行为数字2的个数,以此类推。

【输入样例】

11

【输出样例】

1
4
1
1
1
1
1
1
1
1
 

【题解】

这题很恶心,没错 又是恶心这个词,以后只可能会越来越多地出现这个词。不会减少。。。

我是看着题解写的程序。

首先,从000-999 我们不要删掉多余的0,那么我们会有1000个3位数,然后一共有3000个数字出现过,可以想想0-9,每个数字都只出现一次,00-99,也可以知道0-9每个数字都出现相同的次数。推广一下,000-999每个数字出现的次数也是一样的。

然后3000个数字,0-9有10个,则每个数字都有用到300次。

先别问我0的事!

然后我们举个例子。

6147

我们先看6,6之前有0-5,后3位,都从000-999变化,刚才我们算出来了,每个数字都会用到300次,0-5有6位,所以a[0..9]+=6*300;

然后是0-5这6个数字作为第一位,每个都出现过1000次,即0XXX 1XXX 2XXX...其中XXX ∈ [000,999];

最后是6,6我们要单独处理,要加上148,即6XXX,XXX∈[000..148];

然后处理1,4,7就好。

(这里你用while已经能写出来了,只要按照6的规律就可以)

接下来是0的问题了。

先从只有一位数的情况开始。

比如6;

我们先会看看6后面有没有数字,没有。

然后看看6前面有没有数字,有。要加上几呢? 假设l是数字的长度,我们肯定会这样做的

t = 1

for (int i = 1; i<=l-1;i++)

  t = t *10;

这里如果是上面说的6174,l=4,则t=1000;

但是这里我们是以6为例,所以t = 1;

然后for (int i = 0;i <=5;i++)

  a[i]+=t;

这里已经多出来一个0了。

剩下步骤省略。。

対,如果一位数字会多出1个0;

两位数。

比如12

我们先会看1后面有没有数字,有。

那就用下我们上面的公式。

0-9有10个一位数字。。。。然后每个数字被用一次。

则a[0..9]+=1;

//这里出现的0是多出的。

然后是0 被用了 10 次 0-9,

//这里的0也是多出来的。即00 01 02 03...09;

这里出现了11个多余的0

剩下步骤省略,因为没有出现多余的0.

111

1111

即多出的0是数字的位数。

【代码】

#include <cstdio>
#include <iostream>
#include <string>

using namespace std;

string s1;
unsigned int n;
int a[10];

void input_data()
{
    cin >> s1;
}

void get_ans()
{
    int l = s1.size(); //先获取数据的长度
    for (int i = 0;i <= 9;i++) //每个数字使用的数目初始化
        a[i] = 0;
    int t = 0;
    for (int i = 1;i <= l;i++) //先减去多余的0,即l(字母L)个1(数字1)
        t = t*10 + 1;
    a[0] -= t; //减去多余的0
    while (l > 0) //如果还能继续减少长度 基本上写出第一层第二层就不会有问题了。
        {
            int m = s1[0] - '0'; //先取出头数字
            t = 1;
            for (int i = 1;i <= l-1;i++) //这里是6174中 6时的1000
                t = t * 10;
            int tt = (t * (l-1))/10; //000 - 999 中每个数字被使用的次数 while进行一次就变成00-99
            for (int i = 1;i <= m;i++) //0XXX 1XXX 2XXX 。。。。mXXX 中的 XXX
                for (int j = 0;j <= 9;j++)
                    a[j] += tt;
            for (int i = 0;i <= m-1;i++) //0XXX 1XXX 2XXX ... mXXX中的 1..m
                a[i] += t;
            s1 = s1.erase(0,1); //这是从
            int ttt =0;
            l = s1.size();
            for (int i = 0;i <l;i++)
                ttt = ttt*10 + s1[i] - '0';
            ttt++;
            a[m] += ttt; //这是统计6147 中的148.
        }

}

void output_ans()
{
    for (int i = 0 ;i <= 9;i++)
        printf("%d
",a[i]);
}
	

int main()
{
    input_data();
    get_ans();
    output_ans();
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7632451.html