zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>


    <正文>

    The Counting Problem

    Description

    求 [L,R]内每个数码出现的次数。

    Input Format

    若干行,一行两个正整数 L 和 R。

    最后一行 L=R=0,表示输入结束。

    Output Format

    若干行,对于每个询问做出回答,每行 10 个整数,依次表示 0 至 9 出现的次数。

    输入的最后一行不属于询问,因此不必对此做出回答。

    Sample Input

    1 10
    114 514
    233 666
    19260421 19260817
    19190504 19890605
    0 0
    

    Sample Output

    1 2 1 1 1 1 1 1 1 1
    80 167 180 180 181 95 80 80 80 80
    83 83 150 191 194 194 158 83 83 83
    476 475 476 80 159 180 577 180 97 476
    350124 1059618 450020 450020 450021 450117 450026 450020 440626 1050224
    

    解析

    考虑数位(dp),设(f[i][j][k])代表长度为(i)的数中,最高位为(j),数码(k)的出现次数和。以长度作为阶段,可以轻松转移:

    [f[i][j][k]=sum_{p=0}^9f[i-1][p][k] ]

    当然,对于(j=k)的情况,还要加上(10^{i-1}),作为最高位数码的贡献。

    然后考虑对于一个具体的数值(x),求出(1-x)的答案。

    首先我们可以利用预处理的(dp)数组快速得到长度小于(x)的长度的答案。然后考虑计算长度等于(x)的长度的答案。

    从高位到低位枚举,如果当且位小于(x)的这一位的话,后面的数字可以随便填,直接累加答案即可,反之累加当前位贡献,继续考虑下一位。

    (Code:)

    #include <bits/stdc++.h>
    using namespace std;
    const int SIZE = 13;
    int cnt,num[SIZE];
    long long f[SIZE][10][10],ans[10][2];
    inline long long quickpow(long long a,long long b)
    {
        long long res = 1;
        for ( ; b ; a = a * a , b>>=1 )
            if ( 1 & b ) res = res * a;
        return res;
    }
    inline void Prepdp(void)
    {
        for (int i=0;i<=9;i++) f[1][i][i] = 1;
        for (int i=2;i<=12;i++)
            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];
                f[i][j][j] += quickpow( 10 , i-1 );
            }
    }
    inline void solve(long long x,int id)
    {
        memset( num , 0 , sizeof num );
        cnt = 0; long long y = x;
        while ( x ) num[++cnt] = x % 10 , x /= 10;
        for (int i=0;i<cnt;i++)
            for (int j=1;j<=9;j++)
                for (int k=0;k<=9;k++)
                    ans[k][id] += f[i][j][k];
        for (int i=cnt;i>=1;i--)
        {
            for (int j=0;j<num[i];j++)
            {
                if ( i == cnt && j == 0 ) continue;
                for (int k=0;k<=9;k++)
                    ans[k][id] += f[i][j][k];
            }
            ans[num[i]][id] += y % quickpow( 10 , i-1 ) + 1;
        }
    }
    int main(void)
    {
        Prepdp();
        long long a,b;
        while ( scanf("%lld%lld",&a,&b) && a && b )
        {
            solve( a-1 , 0 ) , solve( b , 1 );
            for (int i=0;i<=9;i++)
                printf("%lld%c",ans[i][1]-ans[i][0]," 
    "[i==9]);
            memset( ans , 0 , sizeof ans );
        }
        return 0;
    }
    

    <后记>

  • 相关阅读:
    XML和HTML中常用转义字符:
    特殊符号大全
    CSS规范
    兼容ie6,ie7,ie8,firefox,chrome浏览器的代码片段
    模拟select选择器
    一行代码解决IE6/7/8/9/10兼容问题
    响应式页面之秘籍
    Global 全局样式基本设置
    webAPP meta 标签大全
    随笔小计 --
  • 原文地址:https://www.cnblogs.com/Parsnip/p/11446916.html
Copyright © 2011-2022 走看看