zoukankan      html  css  js  c++  java
  • bzoj1833: [ZJOI2010]count 数字计数(数位dp)

      学习了一波记忆化数位dp后写这题...我好像写的都跟大家的不一样???跑的还挺快的???(其实全世界一样都是0ms...)

      题目大意:求[a,b]中0~9分别出现几次。(a,b<=10^12)

      dp[pos][num][sum]表示前pos位,求num出现几次,这个数前pos位num已经出现sum次,前导零也很好处理,套记忆化模板就行了。

      (太久没写博客了水一篇...(雾

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #define ll long long
    using namespace std;
    ll dp[20][20][20],a[20],l,r;
    void read(ll &k)
    {
        k=0;ll f=1;char c=getchar();
        while(c>'9'||c<'0')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    ll dfs(int pos,int num,ll sum,bool lead,bool limit)
    {
        if(pos==0)return sum;
        if(!limit && !lead && dp[pos][num][sum]!=-1)return dp[pos][num][sum];
        int up=limit?a[pos]:9;
        ll ans=0;
        if(!lead||pos==1)ans+=dfs(pos-1,num,sum+(num==0),0,limit && a[pos]==0);
        else ans+=dfs(pos-1,num,sum,1,limit && a[pos]==0);
        for(int i=1;i<=up;i++)
        ans+=dfs(pos-1,num,sum+(num==i),0,limit && a[pos]==i);
        if(!limit && !lead)dp[pos][num][sum]=ans;
        return ans;
    }
    ll solve(ll x,int num)
    {
        if(x<0)return 0;
        if(x==0)return num==0?1:0;
        int pos=0;
        while(x)
        {
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,num,0,1,1);
    }
    int main()
    {
        read(l);read(r);
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<=8;i++)
        printf("%lld ",solve(r,i)-solve(l-1,i));
        printf("%lld
    ",solve(r,9)-solve(l-1,9));
    }
    View Code
  • 相关阅读:
    二叉树的存储方式以及递归和非递归的三种遍历方式
    java基础04 匿名内部类
    jvm007 jvm知识点总览
    jvm学习006 jvm内存结构分配
    java基础03 位运算符
    java基础02 数据类型转
    jvm005 从jvm的角度谈谈线程的实现
    Arcgis投影变换后图像变深的问题
    win 7 64位如何安装erdas 9.2
    Win7 64bit 成功安装ArcView3.X
  • 原文地址:https://www.cnblogs.com/Sakits/p/6815468.html
Copyright © 2011-2022 走看看