题目链接: http://gdutcode.sinaapp.com/problem.php?cid=1057&pid=6
题意:求出区间内等凹数字的个数,等凹数字:定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰。
分析:解析一个等凹数字需要满足的条件:必须下降过,必须上升过,必须是回文。那么我们就可以定义出前缀的状态:剩下数位,等凹数长度,前缀末尾的数字,前缀是否下降过,前缀是否上升过,前缀是否为回文。然后搜索出所有前缀含有的等凹数的数量。
AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: [email protected]
************************************************************************/
#include
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 100001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<
#define debug(x) cout << #x" = " << x<
int T;
LL L,R;
int digits[20];
int num[20];
LL DP[20][20][10][2][2][2];
LL dfs(int pos, int len, int pre, bool up, bool down, bool ispa, bool zero, bool limit)
{
if(pos==0) return up&&down&&ispa;
if(!limit && DP[pos][len][pre][up][down][ispa]!=-1) return DP[pos][len][pre][up][down][ispa];
LL ans = 0;
int Max = limit ? digits[pos] : 9;
for(int i=0;i<=Max;i++)
{
num[pos] = i; //深搜路上记录每次选择的数字
if(zero) ans += dfs(pos-1, len-(i==0), i, 0, 0, ispa, (i==0), limit&&i==Max);
else if(i==pre)
{
if(ispa&&pos<=len/2) ans += dfs(pos-1,len,i,up,down,i==num[len+1-pos],zero,limit&&i==Max);
else ans += dfs(pos-1,len,i,up,down,ispa,zero,limit&&i==Max);
}
else if(iif
(up) continue; //如果上升过,就不能下降
if(ispa&&pos<=len/2) ans += dfs(pos-1,len,i,up,true,i==num[len+1-pos],zero,limit&&i==Max);
else ans += dfs(pos-1,len,i,up,true,ispa,zero,limit&&i==Max);
}
else if(i>pre)
{
if(!down) continue; //如果没有下降过,不能上升
if(ispa&&pos<=len/2) ans += dfs(pos-1,len,i,true,down,i==num[len+1-pos],zero,limit&&i==Max);
else ans += dfs(pos-1,len,i,true,down,ispa,zero,limit&&i==Max);
}
}
if(!limit) DP[pos][len][pre][up][down][ispa]=ans;
return ans;
}
LL find(LL x)
{
int pos = 0;
while(x)
{
digits[++pos] = x%10;
x/=10;
}
return dfs(pos,pos,0,false,false,true,true,true);
}
void solve()
{
printf("%lld\n", find(R)-find(L-1));
}
void init()
{
MST(DP,-1);
}
int main()
{
init();
//std::ios::sync_with_stdio(false);
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &L, &R);
solve();
}
//system("pause");
}