• 数位DP


      数位DP是用记忆化搜索做的。个人觉得比较难理解。很对函数中的参数比如前导零什么意思也没有说明,所以导致难以学习。

      记忆化搜索dfs(int len,int pre,int limit); 第二个参数是前导,主要是为了筛选。比如不要1到100000中不要连续数字62,此时你要要记录前导为6,然后你在当前dfs函数中变量时,判断i==2时,不符合要求。limit时一个上限制。

     看题目:hdu2089

    dp[10][2]存储是否是前缀有6的数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int dp[10][2],bit[10];
    
    int dfs(int len,bool if6,bool limit)
    {
        if(!len) return 1;
        if(!limit && dp[len][if6]!=-1) return dp[len][if6];
        int res=0,up = limit ? bit[len] : 9;
        for(int i=0;i<=up;++i)
        {
            if(i==4 || if6&&i==2) continue;
            res += dfs(len-1,i==6,limit&&i==up);
        }
        //不是limit表示里面有0-9的数字
        if(!limit) dp[len][if6] = res;
        return res;
    }
    int fun(int n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,false,true);
    }
    int main()
    {
        memset(dp,-1,sizeof(dp));
        int a,b;
        while(~scanf("%d%d",&a,&b),a&&b)
        {
            printf("%d
    ",fun(b)-fun(a-1));
        }
        return 0;
    }

     hdu3555

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    long long dp[20][2],bit[20];
    
    long long dfs(int len,bool if4,bool limit)
    {
        if(!len) return 1;
        if(!limit && dp[len][if4]!=-1) return dp[len][if4];
        long long res=0,up = limit ? bit[len] : 9;
        for(long long i=0;i<=up;++i)
        {
            if(if4 && i==9) continue;
            res += dfs(len-1,i==4,limit&&i==up);
        }
        if(!limit) dp[len][if4] = res;
        return res;
    }
    long long fun(long long n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,false,true);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        memset(dp,-1,sizeof(dp));
        while(t--)
        {
            long long n;
            scanf("%lld",&n);
            printf("%lld
    ",n-(fun(n)-1));
        }
        return 0;
    }
    View Code

    hdu4722 简单题

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int bit[20];
    long long dp[20][10];
    
    long long dfs(int len,int pre,bool limit)
    {
        if(!len){if(pre==0) return 1;return 0;}
        if(!limit && dp[len][pre] != -1) return dp[len][pre];
        long long res = 0,up = limit ? bit[len] : 9;
        for(int i=0;i<=up;++i)
        {
            res += dfs(len-1,(pre+i)%10,limit && i==up);
        }
        if(!limit) dp[len][pre] = res;
        return res;
    }
    long long fun(long long n)
    {
        int len = 0;
        while(n)
        {
            bit[++len] = n%10;
            n /= 10;
        }
        return dfs(len,0,true);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int t=0;t<T;++t)
        {
            memset(dp,-1,sizeof(dp));
            printf("Case #%d: ",t+1);
            long long a,b;
            scanf("%lld%lld",&a,&b);
            printf("%lld
    ",fun(b) - fun(a-1));
        }
        return 0;
    }
    View Code

    hdu3652 多维度数位DP

    hdu5435 亦或

    hdu4507 恨七不成妻

  • 相关阅读:
    Spring MVC 迁移项目搭建运行
    linux 安装 nginx
    linux 安装 redis
    linux 安装 jdk
    存储过程之游标插入数据
    存储过程之基础语法
    AES加密解密,自定义加密规则记录
    idea破解记录
    Mysql-explain之Using temporary和Using filesort解决方案
    C#多线程学习笔记(朝夕eleven) Task启动方式、Task阻塞、Task.Delay()、多线程异常处理、任务取消、多线程的临时变量、共享数据的lock、Task返回值
  • 原文地址:https://www.cnblogs.com/jlyg/p/7610449.html
Copyright © 2020-2023  润新知