分析
这道题其实很简单,首先我们很容易知道最后一位非零时数字长度小的他的荒谬值小,然后再考虑最后一位会不会为5,能为5的优先选五。
然后可以分为两种情况:
1.形如“5030 8090” r - l大于10^(L的位数 - 1),那长度a肯定是1,这时再先判断非零位为5的是不是在[L~R]这个范围,如果不是再从小到大一个一个的枚举,因为只用改变首位,所以最多只会跑十次。
2.形如“969 1008” r - l小于10^(L的位数 - 1),那长度a肯定大于1,这是我们把R - L的位数求出来,设num为10 ^ (R - L的位数 - 1),将L化为在原区间内且能被num整除的数,再将L依次累加num求最小值即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
int t,l,r;
int Get(int x) {//找荒谬值
int res = 0;
while(!(x % 10)) x /= 10;
if(x % 10 == 5) res --;
while(x) {
x /= 10;
res += 2;
}
return res;
}
void solve() {
int q = l,num = 1;
while(q) {
q /= 10;
num *= 10;
}
num /= 10;
bool flag = 0;
if(l <= num * 5 && num * 5 <= r)
printf("%lld\n",num * 5),flag = 1;
else {//情况1
if(l <= num * 5 * 10 && num * 5 * 10 <= r)//优先选首位为5的
printf("%lld\n",num * 5 * 10),flag = 1;
if(!flag)
for(int i = 1;i <= 10;i ++)//依次枚举
if(l <= num * i && num * i <= r)
{printf("%lld\n",num * i),flag = 1;break;}
}
if(!flag) {//情况二
int q = (r - l + 1),num = 1;
while(q) {
num *= 10;
q /= 10;
}
num /= 10;//找10 ^ (r - l的位数)
int res = 0x7f7f7f7f,ans = l;
int h = (l % num == 0 ? l / num : l / num + 1) * num;//将l化出来
l = h;
for(int i = l;i <= r;i += num) {
if(i > r) break;
int num = Get(i);
if(num < res) {
res = num;
ans = i;
}
}
printf("%lld\n",ans);
}
}
signed main() {
scanf("%lld",&t);
while(t --) {
scanf("%lld %lld",&l,&r);
solve();
}
return 0;
}