【洛谷 P8780】[蓝桥杯 2022 省 B] 刷题统计 题解(二分查找+数学)

[蓝桥杯 2022 省 B] 刷题统计

题目描述

小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a a a 道题目,周六和周日每天做 b b b 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n n n 题?

输入格式

输入一行包含三个整数 a , b a, b a,b n n n.

输出格式

输出一个整数代表天数。

样例 #1

样例输入 #1

10 20 99

样例输出 #1

8

提示

对于 50 % 50 \% 50% 的评测用例, 1 ≤ a , b , n ≤ 1 0 6 1 \leq a, b, n \leq 10^{6} 1a,b,n106.

对于 100 % 100 \% 100% 的评测用例, 1 ≤ a , b , n ≤ 1 0 18 1 \leq a, b, n \leq 10^{18} 1a,b,n1018.

蓝桥杯 2022 省赛 B 组 C 题。


思路

首先定义一个辅助函数ceilDiv,用于实现向上取整的除法操作。

main函数中,首先读取输入的 a a a b b b n n n,然后定义两个变量 l l l r r r,分别表示二分查找的左边界和右边界。这里 r r r的初始值设置得非常大,足以覆盖题目中给定的 n n n的最大值。

接下来进入一个while循环。在每次循环中,计算出当前的中点mid,然后判断是否满足条件,即在mid天内,小明做题的总数大于等于 n n n。如果满足条件,那么将左边界更新为mid,否则将右边界更新为mid。这个过程一直持续到左右边界之间只差1为止。

退出while循环后,先计算出小明在 l l l天内做题的总数,然后从 n n n中减去这个数量,得到剩余的题目数量tmp。同时,将答案ans初始化为 l l l乘以7,这是因为每周有7天。

然后判断tmp是否小于等于5乘以 a a a,也就是判断剩余的题目数量是否可以在周一到周五之间完成。如果可以,那么直接将tmp除以 b b b并向上取整,然后加到ans上;否则,将tmp减去5乘以 a a a,然后将5和tmp除以 b b b并向上取整的结果都加到ans上。

最后,输出ans,这就是小明实现做题数大于等于 n n n的最少天数。

注意

为了防止溢出,在进行二分查找时,应该使用 (5 * a + 2 * b) <= n / mid 进行判断。如果使用 mid * (5 * a + 2 * b) <= n ,无法通过部分测试点。


AC代码

#include <iostream>
using namespace std;
using ll = long long;

ll ceilDiv(ll x, ll y) { return (x + y - 1) / y; }

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	ll a, b, n;
	cin >> a >> b >> n;

	ll l = 0;
	ll r = 1e18 + 7;
	while (l + 1 < r) {
		ll mid = (l + r) >> 1;
		// cout << mid << "\n";
		if ((5 * a + 2 * b) <= n / mid) {
			l = mid;
		} else {
			r = mid;
		}
	}
	// cout << l << "\n";
	ll tmp = n - l * (5 * a + 2 * b);
	ll ans = l * 7;
	// cout << tmp << "\n";
	if (tmp <= 5 * a) {
		ans += ceilDiv(tmp, b);
	} else {
		tmp -= 5 * a;
		ans += 5 + ceilDiv(tmp, b);
	}
	cout << ans << "\n";
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值