其他分享
首页 > 其他分享> > 题解 P4109 【[HEOI2015]定价】

题解 P4109 【[HEOI2015]定价】

作者:互联网

莫名其妙冲到了最优解?

题目链接

Solution [HEOI2015]定价

题目大意:设一个数 \(x\) 去掉后缀零之后为 \(x'\),长度为 \(a\) ,定义 \(x\) 的荒谬度为 \(2a-[x'\;mod\;10\;=5]\),多组询问,求 \([L,R]\) 内荒谬度最小的数(荒谬度相同则取最小的数)

贪心


分析:

首先\(x'\)肯定是越短越好,其次再考虑有没有\(5\)的问题

我们枚举\(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]\)

要使得长度最短,我们肯定选\(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(){
#ifdef LOCAL
	freopen("fafa.in","r",stdin);
#endif
	scanf("%d",&t);
	while(t--)solve();
	return 0;
}

标签:10,res,int,题解,flag,HEOI2015,P4109,荒谬,include
来源: https://www.cnblogs.com/colazcy/p/13771880.html