[HEOI2015]定价 题解

题目

分析

这道题其实很简单,首先我们很容易知道最后一位非零时数字长度小的他的荒谬值小,然后再考虑最后一位会不会为5,能为5的优先选五。

然后可以分为两种情况:

1.形如“5030 8090” r - l大于10^(L的位数 - 1),那长度a肯定是1,这时再先判断非零位为5的是不是在[L~R]这个范围,如果不是再从小到大一个一个的枚举,因为只用改变首位,所以最多只会跑十次。

2.形如“969 1008” r - l小于10^(L的位数 - 1),那长度a肯定大于1,这是我们把R - L的位数求出来,设num为10 ^ (R - L的位数 - 1),将L化为在原区间内且能被num整除的数,再将L依次累加num求最小值即可。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
int t,l,r;
int Get(int x) {//找荒谬值
	int res = 0;
	while(!(x % 10)) x /= 10;
	if(x % 10 == 5) res --; 
	while(x) {
		x /= 10;
		res += 2;
	}
	return res;
}
void solve() {
	int q = l,num = 1;
	while(q) {
		q /= 10;
		num *= 10;
	}
	num /= 10;
	bool flag = 0;
	if(l <= num * 5 && num * 5 <= r)
	printf("%lld\n",num * 5),flag = 1;
	else {//情况1
		if(l <= num * 5 * 10 && num * 5 * 10 <= r)//优先选首位为5的
		printf("%lld\n",num * 5 * 10),flag = 1;
		if(!flag)
		for(int i = 1;i <= 10;i ++)//依次枚举
		if(l <= num * i && num * i <= r)
		{printf("%lld\n",num * i),flag = 1;break;}
	}
	if(!flag) {//情况二
		int q = (r - l + 1),num = 1;
		while(q) {
			num *= 10;
			q /= 10;
		}
		num /= 10;//找10 ^ (r - l的位数)
		int res = 0x7f7f7f7f,ans = l;
		int h = (l % num == 0 ? l / num : l / num + 1) * num;//将l化出来
		l = h;
		for(int i = l;i <= r;i += num) {
			if(i > r) break;
			int num = Get(i);
			if(num < res) {
				res = num;
				ans = i;
			}
		}
		printf("%lld\n",ans);
	}
}
signed main() {
	scanf("%lld",&t);
	while(t --) {
		scanf("%lld %lld",&l,&r);
		solve();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值