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的出错了..

  • 相关阅读:
    Axure chrome 安装及已损坏的解决方法
    Ubuntu16.04上使用git
    ubuntu初探
    nginx入门笔记
    更改element-UI按钮默认样式
    js深拷贝与浅拷贝的区别及实现
    安装mysql-python的遇到的问题
    facebook atc弱网环境搭建和踩坑总结
    验证码识别 Tesseract的简单使用和总结
    selenium 基础(一)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5447617.html
Copyright © 2011-2022 走看看