zoukankan      html  css  js  c++  java
  • fzu2109--Mountain Number(数位dp)

     Problem Description

    One integer number x is called "Mountain Number" if:

    (1) x>0 and x is an integer;

    (2) Assume x=a[0]a[1]...a[len-2]a[len-1](0≤a[i]≤9, a[0] is positive). Any a[2i+1] is larger or equal to a[2i] and a[2i+2](if exists).

    For example, 111, 132, 893, 7 are "Mountain Number" while 123, 10, 76889 are not "Mountain Number".

    Now you are given L and R, how many "Mountain Number" can be found between L and R (inclusive) ?

     Input

    The first line of the input contains an integer T (T≤100), indicating the number of test cases.

    Then T cases, for any case, only two integers L and R (1≤L≤R≤1,000,000,000).

     Output

    For each test case, output the number of "Mountain Number" between L and R in a single line.

     Sample Input

    3
    1 10
    1 100
    1 1000

     Sample Output

    9
    54
    384

    看到题的第一反应是:数位dp。。那肯定不会。。。

    感觉有点像记忆化搜索吧。cal(n)求小于等于n且满足条件的数。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 15;
    int num[N];
    int dp[N][N][2];    // dp[i][j][1] i位数 前一位为j 
    
    int dfs(int nowPos, int preNum, bool isPeak, bool isFirst, bool isMax)
    {
        if (nowPos == -1) return 1;
    
        if (!isMax && dp[nowPos][preNum][isPeak]) return dp[nowPos][preNum][isPeak];
    
        int ans = 0;
        int limit = isMax ? num[nowPos] : 9;
        for (int i = 0; i <= limit; ++i) {
            // isFirst 是说前面都是0 也就是该位是第一位
            if (isFirst && i == 0) ans += dfs(nowPos - 1, 9, false, true, false);
            else if (isPeak && i >= preNum) ans += dfs(nowPos - 1, i, false, false, (isMax && i == limit));
            else if (!isPeak && i <= preNum) ans += dfs(nowPos - 1, i, true, false, (isMax && i == limit));
        }
        if (!isMax) dp[nowPos][preNum][isPeak] = ans;
    
        return ans;
    }
    
    int cal(int n)
    {
        int idx = 0;
        while (n) {
            num[idx++] = n % 10;
            n /= 10;
        }
        return dfs(idx - 1, 9, false, true, true);
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--) {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d
    ", cal(r) - cal(l - 1));
        }
        return 0;
    }
    

      

  • 相关阅读:
    Markdown 语法说明 (简体中文版)
    Markdown Reference
    BZOJ 2229 最小割
    BZOJ 3569 DZY Loves Chinese II
    BZOJ 3563 DZY Loves Chinese
    BZOJ 2956 模积和
    BZOJ 2957 楼房重建
    查漏补缺:面向对象设计原则
    添砖加瓦:设计模式(简单工厂模式)
    添砖加瓦:设计模式(总述)
  • 原文地址:https://www.cnblogs.com/wenruo/p/5141796.html
Copyright © 2011-2022 走看看