【2023百度之星备赛】码蹄集 BD202305 糖果促销(二分)

题目

https://www.matiji.net/exam/brushquestion/5/4347/179CE77A7B772D15A8C00DD8198AAC74?from=1

题目大意:一颗糖果有一张糖纸,p 张糖纸可以换取一颗糖果。换出来糖果的包装纸当然也能再换糖果。小度想吃 k 颗糖果,他需要买多少颗糖?

分析

显然答案具有单调性,即买的糖果越多,最后能吃到的糖果也越多,反之亦然。所以可以考虑二分。具体来说,二分需要买的糖果数,每次二分判断获取到的糖果数是否>=k。如果>=k,说明答案还可以减小。时间复杂度为 O ( T l o g 2 k i ) O(Tlog_2{k_i}) O(Tlog2ki)

另外需要注意特殊情况:

  • p = 1 p=1 p=1的时候,只需要买1个就够了,因为可以一直用吃掉的糖果再换一个糖果,答案为1
  • k = 0 k=0 k=0的时候,显然不需要买糖果,答案为0
  • p = 1 且 k = 0 p=1且k=0 p=1k=0的时候,显然也不需要买糖果,答案为0

所以可以先特判 k = 0 k=0 k=0,再特判 p = 1 p=1 p=1

代码

#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

bool check(ll x, ll p, ll k) {
	ll y = x; // y表示糖纸数
	ll sum = x; // 糖果数
	while (y >= p) {
		sum += y / p; // 当前糖纸数能换的糖果数
		y = y % p + y / p; // 新的糖纸数 = 余下的糖纸数 + 新换的糖果的糖果纸数
	}
	return sum >= k;
}

int main( ) {
	int T;
	scanf("%d", &T);
	while (T -- ) {
		ll p, k;
		scanf("%lld%lld", &p, &k);

		// 特殊情况
        if (k == 0) { 
            cout << 0 << endl;
            continue;
        }
        if (p == 1) {
            cout << 1 << endl;
            continue;
        }

		ll l = 1, r = 1e9;
		ll mid;
		while (l < r) {
			mid = l + r >> 1;
			if (check(mid, p, k))
				r = mid;
			else
				l = mid + 1;
		}
		cout << l << endl; 
	}
	return 0;
}

总结

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值