背景:
昨天
C
S
D
N
CSDN
CSDN好像崩了一段时间。
题目传送门:
https://www.luogu.org/problemnew/show/P4109
题意:
多组询问,在
[
l
,
r
]
[l,r]
[l,r]区间内选出一个数使得用题目的方法求得的贡献尽可能小。
贡献求法:
1.
1.
1.首先将
p
p
p看做一个由数字组成的字符串(不带前导
0
0
0);
2.
2.
2.然后,如果 p 的最后一个字符是
0
0
0,就去掉它。重复这一过程,直到
p
p
p的最后一个字符不是
0
0
0;
3
3
3记
p
p
p的长度为 a,如果此时 p 的最后一位是 5,则荒谬程度为
2
∗
a
−
1
2*a-1
2∗a−1;否则为
2
∗
a
2* a
2∗a。
思路:
一种显然的贪心就是让它有尽可能多的
0
0
0在结尾。不妨每一次尝试将
l
l
l最后的非零位加
1
1
1,尝试是否小于
r
r
r,然后计算贡献,更新答案,这样就可以在保证范围的情况下去让后面的若干位数尽可能为
0
0
0。
由于每一个数的位数为
l
o
g
10
x
log_{10}{x}
log10x很小,所以时间很优秀。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int calc(int x)
{
int tot=1;
while(x>0&&!(x%10)) x/=10,tot*=10;
return tot;
}
int work(int x)
{
int tot=0;
bool flag;
while(x>0&&!(x%10)) x/=10;
flag=(x%10==5);
while(x) x/=10,tot++;
return 2*tot-flag;
}
int main()
{
int T,x,y;
scanf("%d",&T);
while(T--)
{
int mi=(int)(2e9),ans;
scanf("%d %d",&x,&y);
while(x<=y)
{
int op=work(x);
if(op<mi) mi=op,ans=x;
x+=calc(x);
}
printf("%d\n",ans);
}
}