• 数位DP


    数位DP:

     以前遇到数位dp的题都是用其他的方法做的,这些遇到标准的数位dp的题就傻眼了。之前一道题计算1,2的个数,差点摸到数位dp的门槛了。

    入门资料

    基础题

    不要62

    #include <cstdio>
    #include <memory.h>
    
    int dp[8][3];
    //d[l][0]表示不存在不吉利数字 (包含d[l][1])
    //d[l][1]表示不存在不吉利数字,但首位是2 
    //d[l][2]表示存在不吉利的数字
    
    void init() {
        memset(dp, 0, sizeof dp);
        dp[0][0] = 1;
        for (int i = 1; i <= 7; ++i) {
            dp[i][0] = 9 * dp[i - 1][0] - dp[i - 1][1];
            dp[i][1] = dp[i - 1][0];
            //前面加4 ,或者 dp[i - 1][1]前面加6 
            dp[i][2] = 10 * dp[i - 1][2] + dp[i - 1][0] + dp[i - 1][1];
        } 
    }
    
    int sum(int t) {//统计0到t的不吉利的数的个数 
        int len = 0;
        int all = t;
        int digit[8] = {0}; 
        while (t) {
            digit[++len] = t % 10;
            t /= 10;
        }
        int ans = 0; //不吉利的数的个数 
        bool flag = false; //是否已成为不吉利的号 
        int last = 0;
        for (int i = len; i >= 0; --i) {
            ans += dp[i - 1][2] * digit[i];
            if (flag) ans += dp[i - 1][0] * digit[i];
            if (!flag && digit[i] > 4) //当前位可以为4 
                ans += dp[i - 1][0];
            if (!flag && digit[i] > 6) //当前位可以为2,4,6
                 ans += dp[i - 1][1]; //为6,则把前一位的2算上
            if (!flag && last == 6 && digit[i] > 2) //若上一位已经为6,当前位为2 
                ans += dp[i - 1][0]; 
            if(digit[i] == 4 || (last == 6 && digit[i] == 2))
                flag = true;
            last = digit[i];
        }
        return all - ans;
    } 
     
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
        int n, m;
        init();
        while (scanf("%d%d", &n, &m) != EOF && (n != 0 || m != 0)) {
            printf("%d
    ", sum(m + 1) - sum(n));
        } 
        return 0;
    }
    View Code

     题目:有趣的数

    问题描述

    我们把一个数称为有趣的,当且仅当:

    1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。

    2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。

    3. 最高位数字不为0。

    因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。

    请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。

    输入格式
    输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。
    输出格式
    输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。
    样例输入
    4
    样例输出
    3
    答案用的数位dp和记忆化搜索
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <deque>
    #include <list>
     
    using namespace std;
     
    long long f[2000][3][2]; // f[seq_k to place][0: to place 0 , 1: ethier 0 or 1, 2 : must be 1][3 is placed ? 1 : 0]
     
    int dp(int n, int p1, int p3)
    {
             long long &now = f[n][p1][p3];
             if (now != -1)
                       return now;
             if (n == 0)
             {
                       if (p1 == 2 && p3 == 1)
                       {
                                now = 1;
                       }else
                       {
                                now = 0;
                       }
                       return now;
             }
             now = 0;
             if (p1 == 0)
             {
                       now += dp(n-1, 1, p3); // go 0
             }else if (p1 == 1)
             {
                       now += dp(n-1, 1, p3); // go 0
                       now += dp(n-1, 2, p3); // go 1
             }else // p1 == 2
             {
                       now += dp(n-1, 2, p3); // go 1
             }
             
             if (p3 == 0)
             {
                       now += dp(n-1, p1, p3); // go 2;
                       now += dp(n-1, p1, 1); // go 3;
             }else
             {
                       now += dp(n-1, p1, 1); // go 3;
             }
             now %= 1000000007;
    }
     
    int main()
    {
             int n;
             cin >> n;
             memset(f, -1, sizeof(f));
             int ans = dp(n - 1, 0, 0); // seq[n] is 2
             cout << ans << endl;
             return 0;
    }
    View Code
     
  • 相关阅读:
    selenium iframe切换
    roboframework环境搭建与使用
    ServHa双机热备简单配置
    linux搭建java ee开发环境
    FPGA学习笔记(五)—— 组合逻辑电路设计
    FPGA学习笔记(三)—— 数字逻辑设计基础(抽象的艺术)
    FPGA学习笔记(一)——初识FPGA
    FPGA学习笔记(二)——FPGA学习路线及开发流程
    【js重学系列】异步编程
    【js重学系列】作用域
  • 原文地址:https://www.cnblogs.com/fripside/p/3572269.html
Copyright © 2020-2023  润新知