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
  • 相关阅读:
    C++中的指针和数组
    windows系统下JDK1.6环境变量配置
    Java Reflection (JAVA反射)
    转载:cin深入分析(下) – cin的错误处理
    OpenGL总结
    OpenGL纹理
    c/C++内存分配
    转载:cin深入分析(上) – cin输入操作处理
    c++中string的用法
    OpenGL颜色
  • 原文地址:https://www.cnblogs.com/Sakits/p/6815468.html
Copyright © 2011-2022 走看看