数位DP


数位DP

感觉是一种出现很多次的题然而我一次都不会((

数位DP的核心是分情况讨论,找到一个第j位,表示第j位上数字i出现了多少次,最后将每个位数上数字i的出现次数相加即是总和。

对于一个数abcdefg,假定第j位是d,那么有如下可能:

(1)首先对于枚举的数i,如果这个数不是0,那么对于前三位abc,从0到abc,一定会有(0~999)种情况,让d为i,因此

res += l * p;

(2)对于d,我们可以分成三种情况

1.d>i d大于i这个数,则一定有一刻d等于i,则共有efg +1种情况

2.d=i d=i时,后三位可以为任意,则共有000~999种情况

#include <bits/stdc++.h>
using namespace std;

int dgt(int n)
{
    int res = 0;
    while (n)
    {
        n /= 10;
        res++;
    }
    return res;
}

int cnt(int n, int i)
{
    int res = 0, d = dgt(n);
    for (int j = 1; j <= d; j ++ ){ // 分别枚举每一位上的数
        int p = pow(10, j - 1), l = n / p / 10, r = n % p, dj = n / p % 10;
        if (i) res += l * p;
        if (!i && l) res += (l - 1) * p;
        if ((dj > i) && (i || l)) res += p;
        if ((dj == i) && (i || l)) res += r + 1;
    }
    return res;
}

int main()
{
    int a, b;
    while (cin >> a >> b, a)
    {
        if (a > b)
            swap(a, b);
        for (int i = 0; i <= 9; i ++ )
        {
            cout << cnt(b, i) - cnt(a - 1, i) << ' ';
        }
        cout << endl;
    }

    return 0;
}

文章作者: Cedeat
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cedeat !
  目录