您的位置:首页 > 其它

2017广东工业大学程序设计竞赛决赛 Problem G: 等凹数字(回文+数位dp)

2017-03-29 18:27 399 查看
Problem G: 等凹数字

Description

定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?

Input

第一行一个整数T,表示数据的组数。

接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)

Output

输出一个整数,代表[L,R]中有多少等凹数字

Sample Input

2

1 100

101 200

Sample Output

0

1

HINT

小于等于2位的数字无凹峰

套上回文数位dp模板,加上4个维度(上升,下降,前导0,前一个数)看了一下别人解题思路,知道多开这几维才写出来QAQ

代码里有自己的注释

AC代码

#include<stdio.h>
#include<string.h>
int degth[20];
int temp[20];
long long dp[20][20][10][3][3][3];
long long dfs(int pos,int len,int pre,int up,int down,int flag,int f,int k)//长度,当前位,前一位,上升,下降,回文
{
if(len<0) return up&&down&&flag; //上升加下降加是回文
if(!f&&dp[pos][len][pre][up][down][flag]!=-1&&!k)
return dp[pos][len][pre][up][down][flag];
int max=f?degth[len]:9;
long long ret=0;
for(int i=0;i<=max;i++)
{
temp[len]=i;
if(k) //前导0时直接降低长度,否则执行下一位(因为起始位无法判断上升和下降)
ret+=dfs(pos-(k&&i==0),len-1,i,0,0,flag,f&&i==max,k&&i==0);
else if(pre==i)
{
if(flag&&(pos+1)/2>len)
ret+=dfs(pos,len-1,i,up,down,i==temp[pos-len],f&&i==max,k&&i==0);
else ret+=dfs(pos,len-1,i,up,down,flag,f&&i==max,k&&i==0);
}
else if(pre<i)//递增
{
if(!down) continue; //没有下降就上升
if(flag&&(pos+1)/2>len)
ret+=dfs(pos,len-1,i,1,down,i==temp[pos-len],f&&i==max,k&&i==0);
else ret+=dfs(pos,len-1,i,1,down,flag,f&&i==max,k&&i==0);
}
else if(pre>i)//递减
{
if(up) continue;//已经上升过
i
d682
f(flag&&(pos+1)/2>len)
ret+=dfs(pos,len-1,i,up,1,i==temp[pos-len],f&&i==max,k&&i==0);
else ret+=dfs(pos,len-1,i,up,1,flag,f&&i==max,k&&i==0);
}
}
if(!f&&!k) dp[pos][len][pre][up][down][flag]=ret;
return ret;
}
long long solve(long long x)
{
int len=0;
while(x)
{
degth[len++]=x%10;
x/=10;
}
return dfs(len-1,len-1,0,0,0,1,1,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
scanf("%d",&T);
while(T--)
{
long long l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐