[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' imes 10^p)

(L=lceil{frac{l}{10^p}} ceil,R= lfloor{frac{r}{10^p}} floor)

我们可以确定(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
",ans);
}
int t;
int main(){
	scanf("%d",&t);
	while(t--)solve();
	return 0;
}

原文地址:https://www.cnblogs.com/dixiao/p/13811534.html