[lnsyoj4029/luoguP4109/HEOI2015]定价
题意
记 \(x'\) 为 \(x\) 去除后导零的值,则定义 \(f(x)=2(\lfloor\log_{10}x'\rfloor+1) - [x' \equiv 5 \pmod{10}]\),给定区间 \([L,R]\),求该区间中最小的 \(f(x)\) 值。
sol
一道贪心题,思想比较好想,我们需要使得前面的非 0 数字部分长度最小,且末尾尽可能为 \(5\)。具体实现中,我们可以运用倍增思想,向后枚举时使后面的 \(0\) 的部分长度不降,每次枚举判断其 \(f(x)\) 值,这样就可以 \(O(\log R)\) 地枚举,总时间复杂度 \(O(\log^2 R)\)。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int K = 15;
int T;
int l, r;
int p[K];
int count(int x){
int ans = 0;
while (!(x % 10)) ans ++ , x /= 10;
return ans;
}
int calc(int x){
while (!(x % 10)) x /= 10;
int ans = 0;
if (x % 10 == 5) ans -- ;
while (x) ans += 2 , x /= 10;
return ans ;
}
int main(){
p[0] = 1;
for (int i = 1; i < 10; i ++ ) p[i] = p[i - 1] * 10;
scanf("%d", &T);
while (T -- ){
scanf("%d%d", &l, &r);
int ans = 0x3f3f3f3f, id;
for (; l <= r; l += p[count(l)]){
int t = calc(l);
if (t < ans) ans = t, id = l;
}
printf("%d\n", id);
}
return 0;
}