zoukankan      html  css  js  c++  java
  • 【数位DP】HDU 2089 不要62

    HDU 2089 不要62

    int dp[10][2];
    //dp[i][0]表示当前到哪一位,且前一位不是6
    //dp[i][1]表示当前到哪一位,且前一位是6
    int a[20];
    
    LL dfs(int pos,bool six,bool limit){
    //pos搜到的位置(从高位到低位),lead判断是否有前导零,limit判断是否有最高位限制
        int ans = 0;
        if (pos == -1) return 1;
        //搜到最底部,此时数字为个位数并且跳过了4,满足题意,算1个
        if (!limit && dp[pos][six] != -1) return dp[pos][six];
        //如果没有最高位限制且要用到的dp数组已经更新过,直接返回这个结果
        int end = limit ? a[pos] : 9;
        //决定第pos位所能遍历的数字范围
        //如果有最高位限制,则第pos位数字范围最多到原数字的第pos位数字(如原数字4521,不能算出5xxx来)
        //(注意:虽然拆分数字的时候将各个数位倒着储存了,但dfs时也是倒着来的,两者方向其实一致,所以取的是a[pos])
        for (int i = 0; i <= end; i++) {
            if (i == 4 || six && i == 2) continue;
            //这一位是4,跳过;或者前一位是6且这一位是2,构成62,跳过
            ans += dfs(pos - 1, i == 6, limit && i == end);
            //搜低位的dp结果,如果当前有最高位限制且这一位的数字已经是最大的了,则下一位也有最高位限制
            //(如原数字4521,当前搜到4xxx,则接下来最多45xx,不能是46xx)
        }
        if (!limit) dp[pos][six] = ans;
        //如果没有最高位限制,更新dp数组
        return ans;
        //更新dp数组并将结果返回上一层
    }
    
    LL part(LL x)//把数按位拆分
    {
        int len = 0;
        while (x) {
            a[len++] = x % 10;
            //从a[0]开始,并且是倒着的
            //如1234,在数组中为4321
            x /= 10;
        }
        memset(dp, -1, sizeof dp);
        return dfs(len-1,false,true);
        //从len-1开始,即从x的最高位数字开始
    }
    
    int main()
    {
       ios::sync_with_stdio(false);
       // int t; cin >> t; while (t--)
        LL l, r;
        while(cin>>l>>r)
        {
            if (!l && !r) break;
            cout << part(r) - part(l-1)<<endl;
        }
    
    	return 0;
    }
    
  • 相关阅读:
    2012年8月20日 我单身了!
    IE8与VS2008 添加变量 脚本错误的解决方案
    感染导入表方法附源码(转载)
    获取远程网卡MAC地址(VC++)
    [转]VC 中 TreeView 全面解析
    利用INF安装服务启动
    IOCP编程之基本原理
    LIMIT 用法
    SQL Server 触发器的删除操作
    CLRviaCsharp学习笔记
  • 原文地址:https://www.cnblogs.com/streamazure/p/13046963.html
Copyright © 2011-2022 走看看