1 条题解

  • 0
    @ 2025-12-12 16:02:18

    二、 预备知识点总结

    1. 循环模拟for 循环的使用。
    2. 取模运算% 用于判断倍数关系。
    3. 数据类型long long 用于存储大整数。
    4. 逻辑控制if 语句的顺序执行。

    三、 启发式教学:草稿纸上的推理过程

    教练:“我们把时间轴画出来,每一格代表1分钟。” 假设输入:S=5, A=2, B=3, K=2, T=6

    1. t=1:
      • 1%201\%2 \ne 0, 1%301\%3 \ne 0。无事发生。
      • 数量:5。
    2. t=2:
      • 2%2==02\%2 == 0 (繁殖)。数量 ×210\times 2 \to 10
      • 2%302\%3 \ne 0
      • 数量:10。
    3. t=3:
      • 3%203\%2 \ne 0
      • 3%3==03\%3 == 0 (打击)。数量 28-2 \to 8
      • 数量:8。
    4. t=4:
      • 4%2==04\%2 == 0 (繁殖)。数量 ×216\times 2 \to 16
      • 4%304\%3 \ne 0
      • 数量:16。
    5. t=5:
      • 无事发生。
      • 数量:16。
    6. t=6 (关键点!):
      • 6%2==06\%2 == 0 (繁殖)。数量 ×232\times 2 \to 32
      • 6%3==06\%3 == 0 (打击)。数量 230-2 \to 30
      • 注意:如果是先打击再繁殖,就是 (162)×2=28(16-2) \times 2 = 28。结果不一样!题目说先繁殖,所以是 30。

    学生总结:一定要按顺序写 if,不能乱。


    四、 读题关键词总结

    1. “先...再...” \rightarrow 决定了代码中 if 语句的前后顺序。
    2. “归为0” / “灭绝” \rightarrow 需要在每次减少后判断是否 <= 0
    3. TT 分钟” \rightarrow 循环的终点。
    4. “数量翻倍” \rightarrow 指数级增长,警惕数据溢出,使用 long long

    五、 标准题解代码 (C++14)

    /**
     * 题目:细菌的繁殖与生存 (Bacterial Reproduction and Survival)
     * 算法:模拟 (Simulation)
     * 难度:GESP 4级 / CSP-J T1
     */
    
    #include <iostream>
    
    using namespace std;
    
    int main() {
        // 1. 养成使用 long long 的习惯,防止细菌指数爆炸溢出 int
        long long current_bacteria;
        int A, B, K, T;
    
        // 2. 读入数据
        if (!(cin >> current_bacteria >> A >> B >> K >> T)) return 0;
    
        // 3. 按分钟模拟
        for (int t = 1; t <= T; ++t) {
            // 如果细菌已经灭绝,就不需要再模拟了
            if (current_bacteria <= 0) {
                current_bacteria = 0;
                break;
            }
    
            // 4. 判断繁殖 (Prior 1)
            if (t % A == 0) {
                current_bacteria *= 2;
            }
    
            // 5. 判断打击 (Prior 2)
            // 注意:这里不能用 else if,因为可能同时发生
            if (t % B == 0) {
                current_bacteria -= K;
            }
    
            // 6. 每次变化后,检查是否灭绝
            if (current_bacteria <= 0) {
                current_bacteria = 0;
                // 可以选择 break,也可以让循环继续跑(反正 0*2 还是 0)
                // 为了效率,break 更好
                break;
            }
        }
    
        cout << current_bacteria << endl;
    
        return 0;
    }
    

    时间与空间复杂度分析

    • 时间复杂度
      • 循环运行 TT 次。内部操作均为 O(1)O(1)
      • 总复杂度 O(T)O(T)。因为 T100T \le 100,非常快。
    • 空间复杂度
      • 仅使用几个变量,O(1)O(1)

    六、 数据生成器 (Generator.cpp)

    /**
     * 题目:细菌的繁殖与生存
     * 数据生成器
     */
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <random>
    #include <ctime>
    
    using namespace std;
    
    mt19937 rng(time(0));
    
    // 核心解法
    long long solve(long long S, int A, int B, int K, int T) {
        long long cur = S;
        for(int t=1; t<=T; ++t) {
            if(cur <= 0) { cur = 0; break; }
            if(t % A == 0) cur *= 2;
            if(t % B == 0) cur -= K;
            if(cur <= 0) { cur = 0; break; }
        }
        return cur;
    }
    
    void make_case(int id) {
        long long S;
        int A, B, K, T;
    
        switch(id) {
            case 1: // 样例
                S = 10; A = 3; B = 4; K = 5; T = 12;
                break;
            case 2: // 快速灭绝
                S = 10; A = 10; B = 1; K = 10; T = 5;
                break;
            case 3: // 只有繁殖
                S = 1; A = 1; B = 100; K = 0; T = 30; // 2^30,不溢出 long long
                break;
            case 4: // 只有打击
                S = 100; A = 100; B = 1; K = 1; T = 50;
                break;
            case 5: // 同时发生优先繁殖救命
                // T=2: 繁殖x2 -> 20, 打击-15 -> 5. (若先打击则 10-15 < 0 死)
                S = 10; A = 2; B = 2; K = 15; T = 2;
                break;
            case 6: // 随机小数据
                S = rng()%20 + 1;
                A = rng()%5 + 2; 
                B = rng()%5 + 2;
                K = rng()%10 + 1;
                T = 20;
                break;
            case 7: // 增长较快
                S = 100; A = 2; B = 5; K = 10; T = 40;
                break;
            case 8: // 刚好不灭绝
                S = 10; A = 3; B = 3; K = 7; T = 30;
                // 每次 x2 -7 -> 20-7=13 -> 26-7=19 (缓慢增长)
                break;
            case 9: // 刚好灭绝
                S = 10; A = 3; B = 3; K = 20; T = 3;
                // 3分钟: 20 - 20 = 0
                break;
            case 10: // 较大 T
                S = 5; A = 2; B = 100; K = 1; T = 60; // 2^30
                break;
        }
    
        string in_file = to_string(id) + ".in";
        ofstream fout_in(in_file);
        fout_in << S << " " << A << " " << B << " " << K << " " << T << "\n";
        fout_in.close();
    
        string out_file = to_string(id) + ".out";
        ofstream fout_out(out_file);
        fout_out << solve(S, A, B, K, T) << "\n";
        fout_out.close();
    
        cout << "Generated Case " << id << endl;
    }
    
    int main() {
        for(int i=1; i<=10; ++i) make_case(i);
        return 0;
    }
    

    这道题非常适合 GESP 4 级考生,既练习了基础的循环和条件判断,又引入了数据范围(long long)的考量,同时背景故事清晰易懂。希望对你的教学有帮助!

    • 1

    信息

    ID
    19312
    时间
    1000ms
    内存
    32MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者