zoukankan      html  css  js  c++  java
  • 【BZOJ-1833】count数字计数 数位DP

    1833: [ZJOI2010]count 数字计数

    Time Limit: 3 Sec  Memory Limit: 64 MB
    Submit: 2494  Solved: 1101
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    1 99

    Sample Output

    9 20 20 20 20 20 20 20 20 20

    HINT

    30%的数据中,a<=b<=10^6;
    100%的数据中,a<=b<=10^12。

    Source

    Day1

    Solution

    裸的数位DP,但其实并不是特别的水

    首先F[i][j][k]表示位数为i的最高位为j的k种数的个数

    按照十进制拆分,预处理后统计答案

    Code

    #include<iostream> 
    #include<cstdio> 
    #include<algorithm> 
    #include<cstring> 
    #include<cmath> 
    using namespace std; 
    long long L,R; 
    long long F[15][10][10],ans1[10],ans2[10]; 
    void prework() 
    { 
        for (int i=0; i<=9; i++) F[1][i][i]=1; 
        long long tmp=1; 
        for (int i=2; i<=12; i++) 
            { 
                tmp*=10; 
                F[i][0][0]=F[i-1][1][0]*9+F[i-1][0][0]+tmp; 
                for (int j=1; j<=9; j++)  
                    F[i][0][j]=F[i-1][0][j]*9+F[i-1][j][j]; 
                for (int j=1; j<=9; j++) 
                    { 
                        F[i][j][0]=F[i-1][1][0]*9+F[i-1][0][0]; 
                        for (int k=1; k<=9; k++) 
                            if (j==k) 
                                F[i][j][k]=F[i-1][0][k]*9+F[i-1][k][k]+tmp; 
                            else 
                                F[i][j][k]=F[i-1][0][k]*9+F[i-1][k][k]; 
                    } 
            } 
    } 
    long long cf(int x) 
    { 
        long long re=1; 
        for (int i=1; i<x; i++) 
            re*=10; 
        return re; 
    } 
    void Calc(long long x,long long *ans) 
    { 
        int digit[15]={0},len=0; long long y=x; 
        while (x) {digit[++len]=x%10; x/=10;} 
        for (int i=1; i<len; i++) 
            for (int j=1; j<=9; j++) 
                for (int k=0; k<=9; k++) 
                    ans[k]+=F[i][j][k]; 
        for (int i=len; i>=1; i--) 
            { 
                for (int j=0; j<=digit[i]-1; j++) 
                    { 
                        if (i==len && j==0) continue; 
                        for (int k=0; k<=9; k++) ans[k]+=F[i][j][k]; 
                    } 
                ans[digit[i]]+=y%cf(i)+1;            
            } 
    } 
    int main() 
    { 
        prework(); 
        scanf("%lld%lld",&L,&R); 
        Calc(L-1,ans1); Calc(R,ans2); 
        printf("%lld",ans2[0]-ans1[0]); 
        for (int i=1; i<=9; i++) printf(" %lld",ans2[i]-ans1[i]); 
        return 0; 
    }

    自己一开始YY的出错了..

  • 相关阅读:
    用JLabel显示时间-- JAVA初学者遇到的一个困难
    linux下观看b站视频,解决字体乱码
    fedora21 codeblocks在编辑装态下无法输入
    fedora21安装无线驱动
    Hdu 1053 Entropy
    linux下的压缩解压命令 tar 的简单描述
    表的截断、删除、创建
    列的维护
    非分区表的重组
    创建高效且易于管理的表以及表的管理和维护
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5447617.html
Copyright © 2011-2022 走看看