这有一颗山数 [Submit]
Mountain Number
Accept: 433 Submit: 1086
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
日常测试日常难受,今天测试的时候看了一眼,可能就只会这一道题,就在那做呀做,做呀做,旁边的大佬27分钟拿下了First Blood而我,研究了三个小时,WA了7次才得到了欣慰的Accepted,险些爆零,吓死我了,呜呜呜
那么到底什么是山数呢?根据题目的要求就是奇数位上的数字要比他两侧的数字大
一开始我的想法是dfs传参 保留一个数前面的数,和他前前面的数,根据奇数位还是偶数位来判断三个数之间的关系,可能是没写对或者根本就行不通,终于以失败告终
然后我又开一个二维dp数组,写的也是乱七八糟但是求出了第一个和第三个样例的答案,稍微一改之后又求出了第二个样例答案,然后写了两个dfs,开了两个数组,正好把样例过了,就在我提交的时候意识到两个数组是没有关系的,500ms可能过不去,果然给我TLE了。。。于是机智的我灵光一闪,意识到开一个三维数组不就完了吗? 机智个锤锤,人家20分钟就交上了,我摸了三个小时。。。
好了上面的都是废话,现在来说这个题,我们来开一个三维的dp数组
dp[pos][pre][flag]表示的是第pos位,前一位数字是pre,flag为1表示在奇数位,为0则表示在偶数位 出现的合法的山数的数量
核心代码都在这了,注意dfs每深入一次flag就要变化一下,就这这里的 !flag操作
int dfs(int pos,int pre,int flag, int limit){
if(pos<0)return 1;
if(!limit&&dp[pos][pre][flag]!=-1)
return dp[pos][pre][flag];
int res=0;
int up=limit?a[pos]:9;
for(int i=0;i<=up;i++){
if(flag&&i>=pre)
res+=dfs(pos-1,i,!flag,limit&&i==up);
if(!flag&&i<=pre)
res+=dfs(pos-1,i,!flag,limit&&i==up);
}
if(!limit)dp[pos][pre][flag]=res;
return res;
}
还有就是在我们的solve函数中第一次传参的时候,pre要传至少比9要大的数字,这样才能保证第一位数字的小于等于pre,至少可以使得dfs能够进行下去,不然直接return了就没有任何意义了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int mm=20;
int dp[mm][mm][2];
int a[mm];
int dfs(int pos,int pre,int flag, int limit){
if(pos<0)return 1;
if(!limit&&dp[pos][pre][flag]!=-1)
return dp[pos][pre][flag];
int res=0;
int up=limit?a[pos]:9;
for(int i=0;i<=up;i++){
if(flag&&i>=pre)
res+=dfs(pos-1,i,!flag,limit&&i==up);
if(!flag&&i<=pre)
res+=dfs(pos-1,i,!flag,limit&&i==up);
}
if(!limit)dp[pos][pre][flag]=res;
return res;
}
int solve(int x){
if(x==0)return 1;
int cnt=0;
while(x){
a[cnt++]=x%10;
x/=10;
}
return dfs(cnt-1,10,0,1);
}
int main()
{
int t;
scanf("%d",&t);
mem(dp,-1);
while(t--){
int x,y;
scanf("%d%d",&x,&y);
int res=solve(y)-solve(x-1);
printf("%d\n",res);
}
return 0;
}