码迷,mamicode.com
首页 > 其他好文 > 详细

P2602 [ZJOI2010]数字计数

时间:2019-01-09 11:46:17      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:输入格式   inline   print   \n   多少   math   +=   个数   amp   

\(\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%的数据中,\(a\leq b\leq 10^6\)

100%的数据中,\(a\leq b\leq 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? '\n' : ' ');
    return 0;
}

P2602 [ZJOI2010]数字计数

标签:输入格式   inline   print   \n   多少   math   +=   个数   amp   

原文地址:https://www.cnblogs.com/olinr/p/10242375.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!