/*
题目:Mirror Number
题目描述:
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数位的回文数则不是;
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
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; }