51nod 1042数字0-9的数量



基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
 收藏
 关注
给出一段区间a-b,统计这个区间内0-9出现的次数。
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
Input
两个数a,b(1 <= a <= b <= 10^18)
Output
输出共10行,分别是0-9出现的次数
Input示例
10 19
Output示例
1
11
1
1
1
1
1
1
1
1

没什么思路 看了题解前半部分 说跟51nod上一道问1的个数的题很像

题目在这里

基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题
 收藏
 关注
给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。
例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。
Input
输入N(1 <= N <= 10^9)
Output
输出包含1的个数
Input示例
12
Output示例
5

感觉思路真的挺巧妙的 统计各个位数是1的数

比如:12。个位上可能出现1的数为1,11(一共2个),十位上可能出现1的个数为10,11,12(一共3个),加一起正好是5。(至于11是否重复的问题,还是再理解一下上面的做法,这个做法只考虑了每一位出现1的数,11在个位上算和在十位上算是不一样的,所以并没有重复)。

21905:

个位:它出现1的数为:1 ~ 21901,一共 2190 - 0 + 1 = 2191

十位:它出现1的数为:1x ~ 2181x (x 从0到9)一共:(218 - 0 + 1)*10 = 2190

百位:它出现1的数为:1xx ~ 211xx ,一共:(21 - 0 + 1)* 100 = 2200

千位:它出现1的数为:1xxx ~ 11xxx 和 21000 ~ 21905 ,那么很明显,这个情况就比较特殊了,为什么呢?下面再说,我们先计数,一共:(1 - 0 + 1)*1000 + (905 - 0 + 1)= 2000 + 906 = 2906

万位:它出现1的数为:1xxxx ~ 1xxxx,一共:10000


那么现在这道题相当于就是把1009的代码改一下,不仅仅是看1了
把1到a-1的统计一下 1到b的统计一下 相减就是结果了
但是写了以后发现还有问题 因为0比较特殊 不能作为分母 也不能用来取模
改了半天 发现还是得重新写一个针对0的函数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <cmath>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

ll a, b;
ll ansa[10], ansb[10];

ll cntnum(int num, ll n)
{
    ll ans = 0, tmp = n;
    long long tnum = 1;
    while(tmp){
        long long t = tmp % 10;
        if(t < num && num){
            ans += n / (tnum * 10) * tnum;
        }
        else if(t == num){
            if(num){
                ans += n / (tnum * 10) * tnum;
                ans += (n % tnum) + 1;
            }
            else ans++;
        }
        else{
            if(num)ans += (n / (tnum * 10) + 1) * tnum;
            else ans++;
        }

        tnum *= 10;
        tmp /= 10;
    }

    return ans;
}

ll cnt0(ll n)
{
    ll i = 1;
    ll ans = 0;
    ll before = 0, cur = 0, after = 0;
    while((n / i)){
        cur = (n / i) % 10;
        before = n / (i * 10);
        after = n - (before * 10 + cur) * i;
        if(cur == 0){
            ans += (before - 1) * i + after + 1;
        }
        else{
            ans += before * i;
        }
        i *= 10;
    }
    return ans;
}

int main()
{
    while(scanf("%I64d%I64d", &a, &b) != EOF){
        memset(ansa, 0, sizeof(ansa));
        memset(ansb, 0, sizeof(ansb));
        ansa[0] = cnt0(a - 1);
        ansb[0] = cnt0(b);
        for(int i = 1; i <= 9; i++){
            ansa[i] = cntnum(i, a - 1);
            ansb[i] = cntnum(i, b);
            //cout<< ansb[i] - ansa[i]<<endl;
        }
        /*while(a){
            ansa[a % 10]--;
            a /= 10;
        }*/

        for(int i = 0; i <= 9; i++){
            cout<< ansb[i] - ansa[i]<<endl;
        }

    }
    return 0;
}



新改的这份代码应该会更容易理解一点
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <cmath>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

ll a, b;
ll ansa[10], ansb[10];

/*ll cntnum(int num, ll n)
{
    ll ans = 0, tmp = n;
    long long tnum = 1;
    while(tmp){
        long long t = tmp % 10;
        if(t < num){
            ans += n / (tnum * 10) * tnum;
        }
        else if(t == num){
            ans += n / (tnum * 10) * tnum;
            ans += (n % tnum) + 1;
        }
        else{
            ans += (n / (tnum * 10) + 1) * tnum;
        }

        tnum *= 10;
        tmp /= 10;
    }

    return ans;
}*/

ll cnt0(ll n)
{
    ll i = 1;
    ll ans = 0;
    ll before = 0, cur = 0, after = 0;
    while((n / i)){
        cur = (n / i) % 10;
        before = n / (i * 10);
        after = n - (before * 10 + cur) * i;
        if(cur == 0){
            ans += (before - 1) * i + after + 1;
        }
        else{
            ans += before * i;
        }
        i *= 10;
    }
    return ans;
}

ll cntnum(int num, ll n)
{
    ll i = 1;
    ll ans = 0;
    ll before = 0, cur = 0, after = 0;
    while((n / i)){
        cur = (n / i) % 10;
        before = n / (i * 10);
        after = n - (before * 10 + cur) * i;
        if(cur == num){
            ans += before * i + after + 1;
        }
        else if(cur < num){
            ans += before * i;
        }
        else{
            ans += (before + 1) * i;
        }
        i *= 10;
    }
    return ans;
}
int main()
{
    while(scanf("%I64d%I64d", &a, &b) != EOF){
        memset(ansa, 0, sizeof(ansa));
        memset(ansb, 0, sizeof(ansb));
        ansa[0] = cnt0(a - 1);
        ansb[0] = cnt0(b);
        for(int i = 1; i <= 9; i++){
            ansa[i] = cntnum(i, a - 1);
            ansb[i] = cntnum(i, b);
            //cout<< ansb[i] - ansa[i]<<endl;
        }
        /*while(a){
            ansa[a % 10]--;
            a /= 10;
        }*/

        for(int i = 0; i <= 9; i++){
            cout<< ansb[i] - ansa[i]<<endl;
        }

    }
    return 0;
}





原文地址:https://www.cnblogs.com/wyboooo/p/9643445.html