等凹数字
Description
定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样的,仅形成一个等凹峰,如543212345,5544334455是合法的等凹数字,543212346,123321,111111不是等凹数字。现在问你[L,R]中有多少等凹数字呢?
Input
第一行一个整数T,表示数据的组数。
接下来T行每行俩个数字L和R,(1<=L<=R<=1e18)
Output
输出一个整数,代表[L,R]中有多少等凹数字
Sample Input
21 100101 200
Sample Output
01
HINT
小于等于2位的数字无凹峰
解题思路:先找出所有满足条件的数,然后二分查找
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <functional>
#include <climits>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
LL ans[1000009];
int cnt,visit[15];
LL mypow(LL x,LL y)
{
LL sum=1;
while(y)
{
if(y&1) sum*=x;
x*=x;
y>>=1;
}
return sum;
}
void init()
{
queue<LL>q;
cnt=1;
for(int i=1;i<=9;i++) q.push(i),q.push(i*10+i);
for(LL i=2;i<=18;i++)
{
for(LL j=1;j<=9;j++)
q.push(mypow(10,i)*j+j);
}
while(!q.empty())
{
LL pre=q.front();
q.pop();
LL sum=0,res=0;
LL x=pre%10;
memset(visit,0,sizeof visit);
LL m=pre;
while(m)
{
if(!visit[m%10])
{
sum++,visit[m%10]=1;
}
res++;
m/=10;
}
if(sum>1) ans[cnt++]=pre;
if(res+2>18) continue;
for(LL i=x;i<=9;i++)
{
LL nt=mypow(10,res+1)*i+pre*10+i;
q.push(nt);
}
}
sort(ans+1,ans+cnt);
}
int main()
{
init();
//for(int i=1;i<=100;i++) printf("%lld\n",ans[i]);
int t;
scanf("%d",&t);
while(t--)
{
LL l,r;
scanf("%lld%lld",&l,&r);
int k=lower_bound(ans+1,ans+cnt,l)-ans-1;
int kk=upper_bound(ans+1,ans+cnt,r)-ans-1;
printf("%d\n",kk-k);
}
return 0;
}