SPOJ - MYQ10 Mirror Number (数位DP)
原创
©著作权归作者所有:来自51CTO博客作者mb5f5b1df7f1e34的原创作品,请联系作者获取转载授权,否则将追究法律责任
Description
A number is called a Mirror number if on lateral inversion, it gives the same number i.e it looks the same in a mirror. For example 101 is a mirror number while 100 is not.
Given two numbers a and b, find the number of mirror numbers in between them (inclusive of a and b).
Input
First line contains T, number of testcases <= 10^5.
Each testcase is described in a single line containing two numbers a and b.
0 <= a<=b <= 10^44
Output
For each test case print the number of mirror numbers between a and b in a single line.
Example
Input: 3
0 10
10 20
1 4 Output: 3
1
1
算法分析:
数位Dp求回文串,(点击这里),这题要求是1或0或8,且输入为字符串形式(10e44),转化一下就行,难点在于m-1,我们需要单独判断m-1
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[50];
int b[50];
ll dp[50][50][50];
ll dfs(int pos,int s,bool sta,int lead,int limit)
//s表示回文串的起点,pos表示正在搜索的位,sta表示目前构成的串是否为回文串
{
if(pos==-1){
return sta;
}
if(!limit&&!lead&&dp[pos][s][sta]!=-1)
return dp[pos][s][sta];
int up=limit?(a[pos]-'0'):9;
ll tmp=0;
for(int i=0;i<=up;i++)
{
if(i==0||i==8||i==1)
{
b[pos]=i;
if(lead==1&&i==0) //前导0
{
tmp+=dfs(pos-1,s-1,sta,lead,limit&&i==up);
}
else
{
if(sta&&pos<(s+1)/2)//草稿纸看看
//枚举后半段
tmp+=dfs(pos-1,s,b[s-pos]==i,lead && i==0,limit&&i==up);
else //填充前半段
tmp+=dfs(pos-1,s,sta,lead && i==0,limit&&i==up);
}
}
}
if(!limit&&!lead)
dp[pos][s][sta]=tmp;
return tmp;
}
ll solve(string x)
{
int pos=0;
int len=x.length();
for(int i=0;i<len;i++)
a[i]=x[len-1-i];
return dfs(len-1,len-1,1,true,true);//注意sta一开始要初始化为1,找了好久,因为无也是个回文字符串
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
cin>>T;
for(int i=1;i<=T;i++)
{
string n,m;
cin>>n>>m;
ll ans=solve(m)-solve(n);
int len=n.length();
int flag=1;
for(int i=0;i<len;i++)
{
if((n[i]!='8'&&n[i]!='1'&&n[i]!='0')||n[i]!=n[len-i-1])
{
flag=0;
break;
}
}
if(flag==1) ans++;
printf("%lld\n",ans);
}
return 0;
}