/*
题目描述:
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).
大意:求区间[a,b]内有多少个mirror数,mirror数是左右对称的,如0,1,8,11,88,101,111,181,808,818,888等,而其他的包含有非0,1,8数位的回文数则不是;
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.
解题思路:
写一个求F(0,n)区间的mirror数的个数函数,那么答案就是F(b)- F(a-1);
F函数的思路如下:
第一步找出小于等于n,且是回文的数m;
第二步找出小于等于m,且只包含0,1,8,的数x;
第三步把0,1,8看成是三进制,类似于求区间回文数(只不过回文数里面可用的数字有10个,所以是10进制),统计奇数个位和偶数个位上的个数;
最后相加就是答案;
代码:
*/
#include<stdio.h>
#include<string.h>
#define LL long long
int ternary[10],vis[3]={8,1,0};
void getCloseNum(char *num)
{
int i,j,tag;
for(i=1;i<=num[0];i++)
{
tag=-1;
for(j=0;j<3;j++)
{
if(num[i]==vis[j])break;
if(tag<0&&num[i]>vis[j]) tag=j;
}
if(j>=3)
{
num[i++]=vis[tag];
for(;i<=num[0];i++)
num[i]=vis[0];
break;
}
}
if(tag==0){
for(i=1;i<=num[0];i++)if(!num[i])tag++;else break;
for(i=1;i<=num[0]-tag;i++)
num[i]=num[i+tag];
num[0]-=tag;
}
}
LL cal(char *num)
{
LL ans=0;
int i;
for(i=1;i<=num[0];i++)
{
ans*=3;
ans+=ternary[num[i]];
}
return ans+1;
}
void subOne(char * num)
{
int i,ans=1;
for(i=num[0];i>0;i--)
{
num[i]-=ans;
if(num[i]<0)num[i]+=10;
else ans=0;
}
for(i=1;i<=num[0];i++) if(!num[i])ans++;else break;
for(i=1;i<=num[0]-ans;i++)
num[i]=num[i+ans];
num[0]-=ans;
if(num[0]==0)num[0]=1;
}
void Cp(char *a,char *b)
{
int i;
a[0]=b[0];
for(i=1;i<=a[0];i++)a[i]=b[i];
}
LL fun(char *num,int tag)
{
if(num[0]==0)return 0;
getCloseNum(num);
return cal(num)-(tag?0:1);
}
LL find(char *num)
{
int i,tag;
char nextbit[50];
tag=num[0]&1;
Cp(nextbit,num);
num[0]=num[0]/2+(num[0]&1);
for(i=1;i<=nextbit[0]-1;i++)
nextbit[i]=9;
nextbit[0]--;
nextbit[0]=nextbit[0]/2+(nextbit[0]&1);
return fun(num,tag)+fun(nextbit,1-tag);
}
void format(char *num,int has)
{
int i,flag=0,tag;
if(!has){
for(i=1;num[i];i++)num[i]-='0'; num[0]=i-1;
}
tag=num[0]&1;
for(i=1;i<=num[0]/2;i++)
{
if(num[num[0]/2+1-i]<num[num[0]/2+tag+i]) { flag=1;break;}
if(num[num[0]/2+1-i]>num[num[0]/2+tag+i]) { flag=-1;break;}
}
if(flag<0)
{
for(i=2;i<=num[0]/2+tag;i++){
if(num[i])break;
}
if(num[1]==1&&i>(num[0]/2+tag))
{
--num[0];
for(i=1;i<=num[0];i++)
num[i]=9;
}
else{
num[0]=num[0]/2+tag;
subOne(num);
num[0]=2*num[0]-tag;
for(i=num[0]/2+tag+1;i<=num[0];i++)
num[i]=9;
}
}
}
int main()
{
int cas;
char a[50],b[50];
ternary[8]=2;ternary[1]=1;ternary[0]=0;
scanf("%d",&cas);
while(cas--)
{
scanf("%s%s",a+1,b+1);
format(a,0);
format(b,0);
if(a[1]==0&&a[0]==1){
printf("%lld\n",find(b));
continue;
}
subOne(a);
format(a,1);
printf("%lld\n",find(b)-find(a));
}
return 0;
}