Mirror Number (数位dp)

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


题目大概:

找出所给数字间的所有镜像数的数量,不能是252这样的回文数,必须是10801这样的数字。

思路:

和回文数的思路差不多,不过这个题数据量大一点需要字符串来村数据。

而且,这个要判断一下给出的最小的数字是不是镜像数,最后多减了,要加回来。


代码:


#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
int dig[50] , now_dig[50],len;
ll dp[50][50][2];
char num[50];
ll sove(int len,int sta,int flag,int first){
    if(len<0) return (ll)flag;
    if(dp[len][sta][flag]!=-1&&!first)return dp[len][sta][flag];
    int t=(first?dig[len]:9);
    ll res = 0;
    for(int i=0;i<=t;i++) {
        if(i==0||i==1||i==8)
        {
        now_dig[len]=i;
        if(!i&&len==sta)
        {
            res+=sove(len-1,sta-1,flag,first&&i==t);
        }
        else if(flag&&len<(sta+1)/2)
        {
            res+=sove(len-1,sta,i==now_dig[sta-len ],first&&i==t);
        }
        else
        {
            res+=sove(len-1,sta,flag,first&&i==t);
        }
        }
    }
    if(!first) dp[len][sta][flag] = res;
    return res;
}

int check()
{
    for(int i=0;i<=len/2;i++)
    {
        if(dig[i]!=0&&dig[i]!=1&&dig[i]!=8)
        return 0;
        if(dig[i]!=dig[len-1-i])
        return 0;
    }
    return 1;
}
int main() {
    int t;
    scanf("%d" , &t);
    memset(dp , -1 , sizeof(dp));
    while(t--) {
        ll ans1,ans2;
        scanf("%s",num);
        len=strlen(num);
        for(int i=0;i<len;i++)
        {
            dig[i]=num[len-1-i]-'0';
        }
        dig[len]=0;
        ans1=sove(len-1,len-1,1,1)-check();

        scanf("%s",num);
        len=strlen(num);
        for(int i=0;i<len;i++)
        {
            dig[i]=num[len-1-i]-'0';
        }
        dig[len]=0;
        ans2=sove(len-1,len-1,1,1);

        printf("%lld\n" ,ans2-ans1);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值