CF1902B题解

题解 · 2023-12-10

题意

每学期为 $n$ 天,莫诺卡普必须在这 $n$ 天内获得至少 $P$ 分。获得分数有两种途径——完成实践任务或上课。每完成一项实践任务,蒙诺卡普就能获得 $t$ 分;每上一堂课,他就能获得 $l$ 分。

实践任务每七天解锁一个:第一个任务在第 $1$ 天解锁(可以在 $1$ 到 $n$ 的任何一天完成),第二个任务在 $8$ 天解锁(可以在 $8$ 到 $n$ 的任何一天完成),第三个任务在 $15$ 天解锁,以此类推。

从 $1$ 到 $n$ ,每天都有一堂课可以让莫诺卡普参加。每天,莫诺卡普都可以选择是学习还是休息一整天。当蒙诺卡普决定学习时,他可以上一堂课,并完成不超过 $2$ 个解锁了但未完成的任务。如果莫诺卡普全天休息,他将跳过一堂课,并不做任何任务。

求莫诺卡可以休息的最大天数。

$1 \le n, l, t \le 10^9$ ;

$1 \le P \le 10^{18}$。

题解

要求休息的最大天数,等于求不休息的最小天数,显然不休息的天数越多,所获得的学分也越多,所以我们可以二分不休息的天数,设为 $m$。然后我们计算不休息 $m$ 天所能获得的最大学分。

学分由两部分组成——课程和实践任务,所以我们分开计算。课程所获得的学分为 $m \cdot l$。实践任务所获得的学分为 $(\left\lfloor \frac{n - 1}{7} \right\rfloor + 1) \cdot 2m$。

Code:

#include <iostream>
using namespace std;
typedef long long ll;
ll T, n, l, t, P;
ll sum (ll m) {
  return m * l + min (m << 1, (n - 1) / 7 + 1) * t;
}
ll solve () {
  ll L = 0, R = n, M;
  while (L <= R) {
    M = L + R >> 1;
    if (sum (M) >= P) R = M - 1;
    else L = M + 1;
  }
  return R + 1;
}
int main () {
  ios::sync_with_stdio (false);
  cin.tie (0);
  cin >> T;
  while (T--) {
    cin >> n >> P >> l >> t;
    cout << n - solve () << '\n';
  }
  return 0;
}
题解
Theme Jasmine by Kent Liao