P2602 [ZJOI2010]数字计数

Posted olinr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2602 [ZJOI2010]数字计数相关的知识,希望对你有一定的参考价值。

(color{#0066ff}{ 题目描述 })

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

(color{#0066ff}{输入格式})

输入文件中仅包含一行两个整数a、b,含义如上所述。

(color{#0066ff}{输出格式})

输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

(color{#0066ff}{输入样例})

1 99

(color{#0066ff}{输出样例})

9 20 20 20 20 20 20 20 20 20

(color{#0066ff}{数据范围与提示})

30%的数据中,(aleq bleq 10^6)

100%的数据中,(aleq bleq 10^{12})

(color{#0066ff}{ 题解 })

一道基本的数位DP

本来以前做过的,代码太不清真了qwq,改一下

(f[i][j][k])为长度为i,最高位为j,k出现的次数

#include<bits/stdc++.h>
using LL = long long;
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
LL f[25][10][10], base[16];
LL ans1[10], ans2[10];
LL l, r, a[20], num, b[20];
void init() {
    base[0] = 1;
    for(int i = 1; i <= 13; i++) { 
        base[i] = base[i - 1] * 10; 
        for(int j = 0; j <= 9; j++) 
            for(int k = 0; k <= 9; k++) {
                for(int l = 0; l <= 9; l++)
                    f[i][j][l] += f[i - 1][k][l];
                if(j == k) f[i][j][j] += base[i - 1]; //最高位不动,后面随意的贡献
            }

        }
}
void query(LL p, LL *ans) {
    num = 0;
    while(p) {
        a[++num] = p % 10;
        b[num] = b[num - 1] + base[num - 1] * (p % 10);  //从num位开始的数
        p /= 10;
    }
    for(int i = 1; i < num; i++)
        for(int j = 1; j <= 9; j++)
            for(int k = 0; k <= 9; k++)
                ans[k] += f[i][j][k];   //不贴边的
    for(int i = 1; i < a[num]; i++)      //无前导零的贴边
        for(int j = 0; j <= 9; j++)
            ans[j] += f[num][i][j];
    ans[a[num]] += b[num - 1];      //作为某一位的贡献(后面什么数,最高位不变,统计贡献)
    for(int i = num - 1; i >= 1; i--) {
        for(int j = 0; j < a[i]; j++)
            for(int k = 0; k <= 9; k++)  //贴边统计
                ans[k] += f[i][j][k];
        ans[a[i]] += b[i - 1]; 
    }
}

int main() {
    init();
    l = in(), r = in();
    query(l, ans1);
    query(r + 1, ans2);
    for(int i = 0; i <= 9; i++) printf("%lld%c", ans2[i] - ans1[i] , i == 9? '
' : ' ');
    return 0;
}

以上是关于P2602 [ZJOI2010]数字计数的主要内容,如果未能解决你的问题,请参考以下文章

题解P2602 [ZJOI2010]数字计数

P2602 [ZJOI2010]数字计数

P2602 [ZJOI2010]数字计数

P2602 [ZJOI2010]数字计数

P2602 [ZJOI2010]数字计数

Luogu P2602 [ZJOI2010]数字计数