题目分析:
根据题意,在舍去后导零之后的数应该要尽量小,但是这只是对于舍去后导零后末尾数不为 5 5 的情况,末尾数为的时候单独讨论即可,基本上就是这样一个贪心,注意 5000 5000 比 100 100 更优即可,给出贪心乱搞的代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
#define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
#define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
#define Clear(A) memset(A,0,sizeof(A))
#define Copy(A,B) memcpy(A,B,sizeof(A))
using namespace std;
const LL Max=1e3+5;
const LL Mod=1e9+7;
const LL Inf=1e18;
LL T,Left,Right;
inline LL Read(){
LL X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
inline void Write(LL X){
if(X<0)X=-X,putchar('-');
if(X>9)Write(X/10);
putchar(X%10+48);
}
int main(){
LL I,J,K;
T=Read();
while(T--){
Left=Read(),Right=Read();
LL Ans=0;
for(I=1;I<=Left;){
I*=10;
}
if(Left*2<=I&&I<=Right*2){//卡贪心的范围 ,比如Left=400,Right=1100,此时I=1000,根据我们贪心的结论取1000/2=500;
Write(I>>1);putchar('\n');continue;
}
if(I*5<=Right){//同样卡贪心的一个范围,因为500(或者5000)比100更优,比如Left=600,Right=5500,此时I=1000,最优解显然是5000而不是1000
Write(I+(I<<2));putchar('\n');continue;
}I/=10;//降级讨论
for(;I;I/=10){//如果没有寻找到当前贪心的最优解
LL Tmp;
Tmp=Left-Left%I+(bool)(Left%I)*I;// 到Left最近的一个pow(10,K)>=Left,比如Left=600,Right=800时,Tmp=600,显然此时600时是最优解,Left=625时,Tmp=700
if(Right>=Tmp){//判断当前得到的最优解是否在题意的范围也就是<=Right
Write(Ans+Tmp);putchar('\n');break;
}
if(Left%I<=(I>>1)){//讨论下一级
Tmp=Left-Left%I+(I>>1);
if(Right>=Tmp){
Write(Ans+Tmp);putchar('\n');break;
}
}Ans+=Left-Left%I;//更新答案,用最近的一个pow(10,K)<=Left
Left%=I;Right%=I;//Left,Right随着I的降级而降级
}
}
return 0;
}