[HEOI2015]定价
题面
设一个数 \(x\) 去掉后缀零之后为 \(x'\)
长度为 \(a\) ,定义 \(x\) 的荒谬度为 \(2a-[x'\;mod\;10\;= 5]\),多组询问,求 \([L,R]\) 内荒谬度最小的数(荒谬度相同则取最小的数)
算法
根据题意我们知道我们肯定要让最终答案的后缀零尽量多 另外还要考虑最后一位5的存在
我们枚举p \in[0,10]p∈[0,10],表示xx后缀00的个数
枚举\(p \in[0,10]\),表示\(x\)后缀\(0\)的个数
那么\(x = x' \times 10^p\)
令\(L=\lceil{\frac{l}{10^p}}\rceil,R= \lfloor{\frac{r}{10^p}}\rfloor\)
我们可以确定\(x'\in [L,R]x\)
要使得长度最短,我们肯定选\(L\)这个数,考虑到末尾可能有\(5\),我们在\([L,L+10]\)中找最优解即可
代码
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
inline int calc(int x){
int flag = 0,res = 0;
if(x % 10 == 5)flag = -1;
do{
if(x % 10){
if(!flag){
if(x % 10 == 5)flag = -1;
else flag = 1;
}
}
if(flag != 0)res += 2;
x /= 10;
}while(x);
return res + (flag == -1 ? -1 : 0);
}
inline void solve(){
int ans = 0,hm = 0x7fffffff,l,r;
scanf("%d %d",&l,&r);
ll now = 1;
for(int i = 0;i <= 10;i++){
int L = ceil(double(l) / now),R = r / now;
if(L > R)break;
for(int i = L;i <= L + 10 && i <= R;i++)
if(calc(i) < hm)ans = i * now,hm = calc(i);
now *= 10;
}
printf("%d\n",ans);
}
int t;
int main(){
scanf("%d",&t);
while(t--)solve();
return 0;
}