zoukankan      html  css  js  c++  java
  • [ZJOI2010] 数字计数

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:

    1 99

    输出样例#1:

    9 20 20 20 20 20 20 20 20 20

    说明

    30%的数据中,(a<=b<=10^6;)

    100%的数据中,(a<=b<=10^{12}。)

    Solution

    bzoj1883

    数位dp,记忆化搜索

    主要就是解释一下变量

    len指当前搜到哪一位,当len=0时,就返回当前搜到的值
    f表示当前前导0的条件合不合法,初始值是有前导0的,不合法,所以为0
    limit表示当前搜索的这一位有没有限制,即不能超过原数这一数位上的数字,1表示有限制,0表示没有
    sum表示有多少当前已经统计了多少查找的数字
    tq表示当前查找的数字是什么

    本来正常情况下,dp数组是要开四维的,(dp[len][f][limit][sum]),但是由于本题只在没有前导0以及当前位所有数字都搜满的情况下也就是((f) && (!limit)),所以可以省去这两维

    提示:关于数组大小,因为我们统计的数字做多只有15位,所以第1维开16即可,第二维因为每次只统计一个数字x,所以最好情况下就是每一位都是x,最多也就是15位,所以也只要开16

    Code

    #define lol long long
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
     
    using namespace std;
     
    const int N=20;
    
    lol dp[N][N];
    int bit[N];
     
    void in(lol &ans)
    {
        ans=0;lol f=1; char i=getchar();
        while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();}
        while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar();
        ans*=f;
    }
    
    lol dfs(int len,int f,int limit,lol sum,int tq,lol ans=0) {
        if(!len) return sum;
        if(!limit && f &&  dp[len][sum]!=-1) return dp[len][sum];
        int maxn=limit?bit[len]:9;
        for(int i=0;i<=maxn;i++)
    		ans+=dfs(len-1,f||i,limit && i==maxn,sum+((f||i) && (i==tq)),tq);
        if(!limit && f) dp[len][sum]=ans;
        return ans;
    }
    
    lol solve(lol a,int tq,int k=0) {
        memset(dp,-1,sizeof(dp));
        while(a) {
    		bit[++k]=a%10;
    		a/=10;
        }
        return dfs(k,0,1,0,tq);
    }
    int main()
    {
        lol a,b; in(a),in(b);
        for(int i=0;i<10;i++)
    		printf("%lld ",solve(b,i)-solve(a-1,i));
        puts("");
        return 0;
    }
    
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    Emmet使用
    正则参考网址
    sublime通用快捷键 汉化 安装 插件
    【真正福利】成为专业程序员路上用到的各种优秀资料、神器及框架
    生产事故的优化经历
    Windows下oracle打补丁步骤
    Oracle10g完全卸载正确步骤
    在windows2003系统上安装两个版本的oracle
    oracle11g数据库升级数据库升级
    oracle Imp和exp以及导入常见的错误
  • 原文地址:https://www.cnblogs.com/real-l/p/9580501.html
Copyright © 2011-2022 走看看