zoukankan      html  css  js  c++  java
  • poj 2282 The Counting Problem

    http://poj.org/problem?id=2282

    统计[l,r]中每个数码出现的次数

    一个数位dp,之前做的方法是

    dp[i][j]表示到第i位,出现了某个数码j次

    对每个数码做一遍,然后再去除前导零

    比较麻烦

    今天发现新思路

    f[i][0/1][0/1]表示 dfs到第i位之后,是否有上界限制,是否有前导零,填某个数码的数字个数

    g[i][0/1][0/1][j]表示 dfs到第i位之后,是否有上界限制,是否有前导零,数码j的出现次数

    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    int tim,vis[10][2][2];
    long long dp[10][2][2][10],f[10][2][2],ans[10];
    
    int a[10];
    
    void dfs(int dep,int lim,int zero)
    {
        if(vis[dep][lim][zero]==tim) return;
        vis[dep][lim][zero]=tim;
        if(!dep)
        {
            f[dep][lim][zero]=1;
            return;
        }
        int up=lim ? a[dep] : 9,nl,nz;
        for(int i=0;i<=up;++i)
        {
             nl=lim && i==a[dep];
             nz=zero && !i; 
             dfs(dep-1,nl,nz);
             f[dep][lim][zero]+=f[dep-1][nl][nz];
             if(!nz) dp[dep][lim][zero][i]+=f[dep-1][nl][nz];
             for(int j=0;j<=9;++j) dp[dep][lim][zero][j]+=dp[dep-1][nl][nz][j];
        }
    }
    
    void solve(int n,int ty)
    {
        int len=0;
        while(n) a[++len]=n%10,n/=10;
        tim++;
        memset(f,0,sizeof(f));
        memset(dp,0,sizeof(dp));
        dfs(len,1,1); 
        for(int i=0;i<=9;++i) ans[i]+=ty*dp[len][1][1][i];
    }
    
    int main()
    {
        int l,r;
        while(1)
        {
            scanf("%d%d",&l,&r);
            if(!l && !r) return 0;
            if(l>r) l^=r,r^=l,l^=r; 
            memset(ans,0,sizeof(ans));
            solve(r,1);
            solve(l-1,-1);
            for(int i=0;i<=9;++i) printf("%lld%c",ans[i],i==9 ? '
    ' : ' '); 
        } 
    }
  • 相关阅读:
    js 函数声明和函数表达式的区别
    使用dom4j工具包对xml文件解析
    xml的schema约束
    xml的DTD约束
    C3P0连接池工具类使用
    jdbc连接警告不安全
    java的unity单元测试
    BootStrap容器介绍
    validate插件实现表单效验(二)
    validate插件实现表单效验(一)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12372802.html
Copyright © 2011-2022 走看看