Fzu2109 Mountain Number 数位dp

Accept: 189    Submit: 461
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 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

 Source

“高教社杯”第三届福建省大学生程序设计竞赛
 
某次群赛的一个很水的数位dp,但脑抽了,不知道想到哪里去了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
int bits[20];
ll dp[20][15][2][2];
ll dfs(int pos, int pre, int iso, int doing) {
    if(pos == -1) return 1;
    int End = doing ? bits[pos] : 9;
    ll& ans = dp[pos][pre][iso][doing];
    if(ans != -1) return ans;
    ans = 0;
    for(int i = 0; i <= End; ++i) {
        if(iso && i <= pre) ans += dfs(pos - 1, i, 0, doing && i == End);
        else if(!iso && i >= pre) ans += dfs(pos - 1, i, 1, doing && i == End);
    }
    return ans;
}
ll calc(ll x) {
    int ls = 0;
    memset(dp, -1, sizeof dp);
    while(x) {
        bits[ls++] = x % 10;
        x /= 10;
    }
    return dfs(ls - 1, 9, 1, 1);
}
int main() {
    ll n, m;
    int _;
    cin >> _;
    while(_ --) {
        cin >> n >> m;
        cout << calc(m) - calc(n - 1) << endl;
    }
    return 0;
}
View Code

 

posted @ 2016-01-24 20:33  JL_Zhou  阅读(180)  评论(0编辑  收藏  举报