动态规划(5)-------数位统计DP

真的是羡慕那些高智商的人,看了好多博客才有一丝丝的感觉。
老规矩,还是看y总的网站,感觉里面有的的题解写的真的是nice!

计数问题

虽然暴力也能做,但是这个数据范围太大了…所以直接放弃暴力…
思路:假如一个数n=abcdefg,按照位来统计的话。

1.假如统计第4位的数字,让前三位位于000~ abc-1,那么后三位就可以取000~ 999,所以总共有abc*1000中取法。

2.假如前三位取abc,那么第四位有三种情况,第一种是dx,efg就有000~ 999这1000种取法,把这四种情况和加起来,在判断一下0的情况,因为0不能为首位,最后得到的答案就是所求的答案…具体代码看大佬的代码,小弟不才,自己写的代码实在是不好拿出来…

(大佬代码)

# include 
# include 
using namespace std;

int dgt(int n) // 计算整数n有多少位
{
    int res = 0;
    while (n) ++ res, n /= 10;
    return res;
}

int cnt(int n, int i) // 计算从1到n的整数中数字i出现多少次 
{
    int res = 0, d = dgt(n);
    for (int j = 1; j <= d; ++ j) // 从右到左第j位上数字i出现多少次
    {
        // l和r是第j位左边和右边的整数 (视频中的abc和efg); dj是第j位的数字
        int p = pow(10, j - 1), l = n / p / 10, r = n % p, dj = n / p % 10;
        // 计算第j位左边的整数小于l (视频中xxx = 000 ~ abc - 1)的情况
        if (i) res += l * p; 
        if (!i && l) res += (l - 1) * p; // 如果i = 0, 左边高位不能全为0(视频中xxx = 001 ~ abc - 1)
        // 计算第j位左边的整数等于l (视频中xxx = abc)的情况
        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;
}

这个题还可以这样做:

大佬博客

因为都是理解别人的代码,想看的话大家直接点开看就ok了。小编先暂时不写了,等自己有了新见解再补,因为大佬写的太漂亮了。

你可能感兴趣的:(动态规划)