分析
看着像数位DP,但是貌似状态不太好定义,而有一些特殊性质,于是用这种思想去做题,也就是枚举每一位填的数字去填,加上判定就行。
第一种情况,两个数位数不同,那一定可以找到一个位数与较短的一个相同的,幸运值为0的数。启示我们填数只需要记录位数较少的一个的位数就行。
第二种情况,位数相同。我们枚举数字的最大值和最小值,然后一位一位填。每填上一位的时候就把后面的全部“补齐”,具体就是全都补齐最小的那个数,然后与下界比较,补齐最大的那个数然后与上界比较。
如果比下界还小,那补齐用的数字可以继续增大,如果比上界还大,那证明与补齐无关,就是这一位填大了。直到有一个数可以满足这两个条件,那就确定为可以填的数。
如果一个数填好了出来就统计答案。
官方题解:
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll t;
int a[20],b[20];
ll l,r,L,R,ans=20,anss;
int main()
{
cin>>t;
while(t--)
{
scanf("%lld%lld",&L,&R);
if(L<10)
{
cout<<L<<endl;
continue;
}
int tot=0;
l=L;
while(L)
{
a[++tot]=L%10;
L/=10;
}
for(int mn=0;mn<=9;mn++)
{
for(int mx=mn;mx<=9;mx++)
{
ll res=0;
int ff;
for(int i=1;i<=tot;i++)
{
ff=-1;
for(int j=mn;j<=mx;j++)
{
ll nowr=res*10+j;
for(ll k=i+1;k<=tot;k++) nowr=nowr*10+mn;
if(nowr>r) break;
ll nowl=res*10+j;
for(ll k=i+1;k<=tot;k++) nowl=nowl*10+mx;
if(nowl<l) continue;
ff=j;
break;
}
res=res*10+ff;
if(res>=l&&res<=r)
{
if(ans>mx-mn)
{
ans=mx-mn;
anss=res;
}
}
}
if(ff!=-1)
{
if(ans>mx-mn)
{
ans=mx-mn;
anss=res;
}
}
}
}
printf("%lld\n",anss);
ans=20;
}
return 0;
}
/*一堆破烂代码,狗过去了,懒得改了,有空再改*/