题解:学而思编程 冲刺信奥

【题目来源】

学而思编程:冲刺信奥

【题目描述】

不知不觉已经进入炎热的夏天,小猴发现暑假完了之后今年的CSP-J就临近比赛了,所以小猴想提前做好复习规划:小猴决定从下周一开始努力刷题备战CSP-J,他计划周一至周五每天做 \(a\) 道题目,周六和周日每天做 \(b\) 道题目。

请你帮小猴计算,按照计划他将在第几天实现做题数大于 \(n\) 题?

【输入】

一行包含三个整数 \(a\)\(b\)\(n\)

【输出】

一行,一个整数代表天数。

【输入样例】

10 20 99

【输出样例】

8

【核心思想】

  1. 问题分析:给定周一至周五每天做 \(a\) 题、周六周日每天做 \(b\) 题的计划,求累计做题数首次超过 \(n\) 题所需的天数。这是一个周期模拟问题,核心在于利用周期性规律减少重复计算,将大规模模拟优化为整周计算 + 剩余天数模拟。

  2. 算法选择

    • 周期分解:以 \(7\) 天为一个周期,先计算完整周期的数量,再模拟剩余不足一周的天数
    • 取模运算:利用 \(n \bmod s\) 提取不足一个周期的剩余量,避免逐天遍历所有天数
  3. 关键步骤

    • 计算周工作量\(s = 5 \times a + 2 \times b\),即一个完整周期(\(7\) 天)的总做题量
    • 整周处理\(res = \lfloor n / s \rfloor \times 7\),计算完整周期对应的天数,\(n \leftarrow n \bmod s\) 得到剩余目标量
    • 模拟剩余天数:定义周期内每日工作量数组 \(d = [a, a, a, a, a, b, b]\),逐天累加 \(sum\),直到 \(sum > n\)
    • 总天数累加\(res \leftarrow res + day\),其中 \(day\) 为最后不足一周所需的天数
    • 输出结果\(res\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(1)\),整周计算为 \(O(1)\),剩余天数模拟最多 \(7\) 天,亦为 \(O(1)\)
    • 空间复杂度:\(O(1)\),仅需常数级别变量和固定长度为 \(7\) 的数组
  5. 周期模拟的核心思想

    • 周期性规律利用:当操作具有固定周期时,不必逐天模拟,而是通过除法快速跳过完整周期,大幅降低时间复杂度
    • 取模提取余量\(n \bmod s\) 将大规模问题缩小为周期内的局部问题,使得剩余部分可以在常数时间内完成模拟
    • 边界条件处理:循环条件使用 \(sum \leq n\) 确保累计量严格大于 \(n\) 时才停止,满足题目"大于 \(n\) 题"的要求
    • 防溢出处理:使用 long long 避免 \(5 \times a + 2 \times b\)\(a, b\) 较大时发生整数溢出
    • 适用于具有固定周期规律、需要计算累计量达到阈值所需步数的模拟类问题

【解题思路】

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long           // 将 int 定义为 long long,防止乘法溢出

signed main()                   // 使用 signed 替代 int,因为 #define int long long
{
    int a, b, n;                // a: 周一至周五每天做题数, b: 周六周日每天做题数, n: 目标做题总数
    cin >> a >> b >> n;         // 读入三个整数

    int s = 5 * a + 2 * b;      // s: 一周(7天)的总做题量 = 5天×a + 2天×b

    int res = n / s * 7;        // res: 完整周数对应的天数
                                // n/s 得到完整周数,乘以7得到完整周的天数

    int sum = 0;                // sum: 当前周内累计做题数

    n %= s;                     // n: 剩余不足一周的做题量

    // 一周每天的工作量数组:周一到周五每天a题,周六周日每天b题
    int d[] = {a, a, a, a, a, b, b};

    int day = 0;                // day: 当前周内经过的天数

    // 模拟不足一周的做题过程,直到累计做题数超过剩余目标n
    while (sum <= n)            // 当累计工作量小于等于剩余目标时继续
    {
        day++;                  // 天数增加
        sum += d[(day - 1) % 7];    // 加上当天工作量,用模7循环取一周中的某天
    }

    res += day;                 // 总天数 = 完整周天数 + 最后不足一周的天数

    cout << res << endl;        // 输出实现做题数大于n所需的总天数

    return 0;
}

【运行结果】

10 20 99
8
posted @ 2026-07-06 21:05  团爸讲算法  阅读(17)  评论(0)    收藏  举报