• HDU 数位dp


    模板http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html

    完全理解以后,我发现这种写法实在是太厉害了,简洁,优美,可以回避很多细节问题,而这些细节如果用递推的方法写,处理起来可能会非常痛苦

    http://acm.hdu.edu.cn/showproblem.php?pid=2089

    不要62

    http://www.cnblogs.com/xiaohongmao/p/3473599.html

    前几天写过这道题的解题报告,两种解法都有

    http://acm.hdu.edu.cn/showproblem.php?pid=3555

    不要49

    #include <iostream>
    using namespace std ;
    typedef __int64 ll ;
    ll dp[25][2] ;
    int digit[25] ;
    ll dfs(int i,int s,bool e)
    {
        if(!i)return 1 ;
        if(!e && dp[i][s]!=-1)
            return dp[i][s] ;
        ll res=0 ;
        int u=e?digit[i]:9 ;
        for(int d=0 ;d<=u ;d++)
        {
            if(s && d==9)
                continue ;
            res+=dfs(i-1,d==4,e&&d==u) ;
        }
        return e?res:dp[i][s]=res ;
    }
    int callen(ll n)
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(ll n,int len)
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    ll solve(ll n)
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        return dfs(len,0,1) ;
    }
    int main()
    { 
        int t ;
        scanf("%d",&t) ;
        memset(dp,-1,sizeof(dp)) ;
        while(t--)
        {
            ll n ;
            scanf("%I64d",&n) ;
            printf("%I64d
    ",n+1-solve(n)) ;
        }
        return 0 ;
    }
    View Code

    http://acm.hdu.edu.cn/showproblem.php?pid=3652

    出现13且是13的倍数

    #include <iostream>
    using namespace std ;
    int dp[15][15][2][15] ;//当前位数 被13除的余数 是否包括13 最末一位数 
    int digit[15] ;
    int dfs(int i,int re,bool flag,int last,bool e)
    {
        if(!i)return !re && flag ;
        if(!e && dp[i][re][flag][last]!=-1)
            return dp[i][re][flag][last] ;
        int res=0 ;
        int u=e?digit[i]:9 ;
        for(int d=0 ;d<=u ;d++)
            res+=dfs(i-1,(re*10+d)%13,flag || (last==1 && d==3),d,e && d==u) ;
        return e?res:dp[i][re][flag][last]=res ;
    }
    int callen(int n)
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(int n,int len)
    {
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    int solve(int n)
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        return dfs(len,0,0,0,1) ;
    }
    int main()
    {
        int n ;
        memset(dp,-1,sizeof(dp)) ;
        while(~scanf("%d",&n))
        {
            printf("%d
    ",solve(n)) ;
        }
        return 0 ;
    }
    View Code

    http://acm.hdu.edu.cn/showproblem.php?pid=4389

    和上一题很像,要求x整除f(x),由于f(x)范围较小,枚举f(x)就好,注意的地方是有点卡内存,数组要开的比较合适才能过,习惯性开大点会MLE

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std ;
    int digit[11] ;
    int dp[11][84][84][84] ;
    int w ;
    int dfs(int i,int s,int mod,int e)
    {
        if(!i)return !mod && s==w ;
        if(!e && dp[i][s][mod][w]!=-1)return dp[i][s][mod][w] ;
        int u=e?digit[i]:9 ;
        int res=0 ;
        for(int d=0 ;d<=u ;d++)
            res+=dfs(i-1,s+d,(mod*10+d)%w,e && d==u) ;
        return e?res:dp[i][s][mod][w]=res ;
    }
    int callen(int n)
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(int n,int len)
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    int solve(int n)
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        int ans=0 ;
        for(w=1 ;w<84 ;w++)
            ans+=dfs(len,0,0,1) ;
        return ans ;
    }
    int main()
    {
        memset(dp,-1,sizeof(dp)) ;
        int t ;
        scanf("%d",&t) ;
        for(int cas=1 ;cas<=t ;cas++)
        {
            int l,r ;
            scanf("%d%d",&l,&r) ;
            printf("Case %d: %d
    ",cas,solve(r)-solve(l-1)) ;
        }
        return 0 ;
    }
    View Code

    http://acm.hdu.edu.cn/showproblem.php?pid=3709

    枚举平衡位置

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std ;
    typedef __int64 ll ;
    int digit[25] ;
    ll dp[25][25][1500] ;
    int w ;
    ll dfs(int i,int s,int e)
    {
        if(!i)return !s ;
        if(!e && dp[i][w][s]!=-1)return dp[i][w][s] ;
        int u=e?digit[i]:9 ;
        ll res=0 ;
        for(int d=0 ;d<=u ;d++)
            res+=dfs(i-1,s+d*(i-w),e && d==u) ;
        return e?res:dp[i][w][s]=res ;
    }
    int callen(ll n)
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(ll n,int len)
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    ll solve(ll n)
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        ll ans=0 ;
        for(w=1 ;w<=len ;w++)
            ans+=dfs(len,0,1) ;
        return ans-len+1 ;
    }
    int main()
    {
        memset(dp,-1,sizeof(dp)) ;
        int t ;
        scanf("%d",&t) ;
        while(t--)
        {
            ll l,r ;
            scanf("%I64d%I64d",&l,&r) ;
            printf("%I64d
    ",solve(r)-solve(l-1)) ;
        }
        return 0 ;
    }
    View Code

     http://acm.hdu.edu.cn/showproblem.php?pid=4722

    和4389一样,不过除数只有10一个,更简单

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std ;
    typedef __int64 ll ;
    int digit[25] ;
    ll dp[25][105][15] ;
    ll dfs(int i,int s,int mod,int e)
    {
        if(!i)return !mod ;
        if(!e && dp[i][s][mod]!=-1)return dp[i][s][mod] ;
        int u=e?digit[i]:9 ;
        ll res=0 ;
        for(int d=0 ;d<=u ;d++)
            res+=dfs(i-1,s+d,(mod+d)%10,e && d==u) ;
        return e?res:dp[i][s][mod]=res ;
    }
    int callen(ll n)
    {
        int cnt=0 ;
        while(n)
        {
            cnt++ ;
            n/=10 ;
        }
        return cnt ;
    }
    void caldigit(ll n,int len)
    {
        memset(digit,0,sizeof(digit)) ;
        for(int i=1 ;i<=len ;i++)
        {
            digit[i]=n%10 ;
            n/=10 ;
        }
    }
    ll solve(ll n)
    {
        int len=callen(n) ;
        caldigit(n,len) ;
        return dfs(len,0,0,1) ;
    }
    int main()
    {
        memset(dp,-1,sizeof(dp)) ;
        int t ;
        scanf("%d",&t) ;
        for(int cas=1 ;cas<=t ;cas++)
        {
            ll l,r ;
            scanf("%I64d%I64d",&l,&r) ;
            printf("Case #%d: %I64d
    ",cas,solve(r)-solve(l-1)) ;
        }
        return 0 ;
    }
    View Code


     

  • 相关阅读:
    一起谈.NET技术,深入ASP.NET 2.0的提供者模型(2) 狼人:
    一起谈.NET技术,从.NET中委托写法的演变谈开去(上):委托与匿名方法 狼人:
    一起谈.NET技术,将Flash 嵌入WPF 程序 狼人:
    一起谈.NET技术,数组排序方法的性能比较(中):Array.Sort<T> 实现分析 狼人:
    人一生当中最应该珍惜的十种人
    《程序员的第一年》复习一下C#的【封装 多态 继承 简单计算器源码实例】
    myeclipse 修改模板
    三星将在百思买零售店内开设1400家体验店
    谷歌Q3推Android本 蚕食自己平板市场
    Spring Setting
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/3538944.html
Copyright © 2020-2023  润新知