• 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


     

  • 相关阅读:
    基于Haproxy+Keepalived构建高可用负载均衡集群
    基于 Haproxy 构建负载均衡集群
    shell for循环练习题99乘法表
    帮软件同事写的vsftpd服务虚拟用户管理脚本
    sed文件处理练习题
    判断ssh登录密码验证错误超过5次的IP被拉黑
    使用shell中数组功能生成自己的手机号
    利用Crontab设置每个月第一个周六的17:30执行/opt/shell.sh 脚本
    Tomcat 项目代码上线步骤详解
    Jar/War/Ear等包的作用与区别详解
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/3538944.html
Copyright © 2020-2023  润新知