当前位置: 首页 > news >正文

模运算专题练习 ——基于罗勇军老师的《蓝桥杯算法入门C/C++》

目录

一、1.刷题统计 - 蓝桥云课

算法代码:

代码思路分析 

二、1.倍数问题 - 蓝桥云课

算法代码: 

代码思路

关键逻辑详解


一、1.刷题统计 - 蓝桥云课

算法代码:

#include <bits/stdc++.h>  // 包含所有标准库头文件
using namespace std;     // 使用标准命名空间,避免每次调用标准库函数时写 std::
typedef long long ll;    // 定义 ll 为 long long 类型的别名,方便使用

int main() {
    // 定义变量 a(工作日每天完成的任务数)、b(周末每天完成的任务数)、n(总任务数)
    ll a, b, n;
    // 从标准输入读取 a、b、n 的值
    cin >> a >> b >> n;

    // 计算一周(7 天)完成的任务量:5 个工作日每天完成 a 个任务,2 个周末每天完成 b 个任务
    ll week = a * 5 + b * 2;

    // 计算完整周的天数:总任务数除以一周的任务量,取整后乘以 7
    ll days = (n / week) * 7;

    // 计算剩余的任务量:总任务数对一周的任务量取模
    ll k = n % week;

    // 如果有剩余任务需要处理
    if (k <= a * 5) {
        // 如果剩余任务可以在 5 个工作日内完成
        // 计算需要多少个工作日完成剩余任务
        days += k / a;
        // 如果剩余任务不能整除 a,则需要额外一天
        if (k % a) {
            days += 1;
        }
    } else {
        // 如果剩余任务需要跨到周末完成
        // 先完成 5 个工作日
        days += 5;
        // 计算剩余任务量:减去 5 个工作日完成的任务量
        k -= a * 5;
        // 计算需要多少个周末完成剩余任务
        days += k / b;
        // 如果剩余任务不能整除 b,则需要额外一天
        if (k % b) {
            days += 1;
        }
    }

    // 输出总天数
    cout << days;

    // 主函数返回 0,表示程序正常结束
    return 0;
}

代码思路分析 

二、1.倍数问题 - 蓝桥云课

算法代码: 

#include <bits/stdc++.h>  // 包含所有标准库头文件
using namespace std;     // 使用标准命名空间,避免每次调用标准库函数时写 std::

int m[1050][3];  // 定义二维数组 m,用于存储每个余数对应的最大三个数
int u[100010];   // 定义数组 u,用于存储输入的整数

int main() {
    int n, k;  // 定义变量 n(数组大小)和 k(模数)
    cin >> n >> k;  // 输入 n 和 k

    // 输入数组 u
    for (int i = 0; i < n; i++) {
        scanf("%d", &u[i]);
    }

    // 将数组 u 按从大到小排序
    sort(u, u + n, greater<int>());

    // 遍历数组 u,按模数分类
    for (int i = 0; i < n; i++) {
        int y = u[i] % k;  // 计算当前数对 k 取模的结果
        // 将当前数存储到 m[y] 中,最多存储三个数
        if (m[y][0] == 0) {
            m[y][0] = u[i];
        } else if (m[y][1] == 0) {
            m[y][1] = u[i];
        } else if (m[y][2] == 0) {
            m[y][2] = u[i];
        }
    }

    int ans = 0;  // 定义变量 ans,用于存储最终的最大和

    // 枚举可能的和 x(x 是 k 的倍数,范围为 0 到 2k)
    for (int x = 0; x <= 2 * k; x += k) {
        // 枚举余数 a
        for (int a = 0; a < k; a++) {
            // 枚举余数 b
            for (int b = 0, c; b < k; b++) {
                // 计算余数 c = x - a - b
                c = x - a - b;
                // 检查 c 是否合法(即 c 在 0 到 k-1 之间)
                if (c >= 0 && c < k) {
                    // 计算当前组合的和,并更新最大值
                    ans = max(ans, m[a][0] + m[b][a == b] + m[c][(a == c) + (b == c)]);
                }
            }
        }
    }

    // 输出结果
    cout << ans;
    return 0;  // 主函数返回 0,表示程序正常结束
}

代码思路

        这段代码的目的是从一组整数中选出 最多三个数,使得它们的和是 k 的倍数,并且和尽可能大。具体思路如下:

  1. 输入数据

    • 读取整数 n(数组大小)和 k(模数)。

    • 读取数组 u,存储 n 个整数。

  2. 排序数组

    • 将数组 u 按从大到小排序,方便后续优先选择较大的数。

  3. 按模数分类

    • 使用二维数组 m 记录每个余数对应的最大三个数。

    • 遍历数组 u,计算每个数对 k 取模的结果 y=u[i]%k。

    • 将数 u[i] 存储到 m[y]中,最多存储三个数(即每个余数最多记录三个最大的数)。

  4. 枚举可能的和

    • 枚举可能的和 x,其中 x 是 k 的倍数,范围为 0 到2k(因为最多选三个数,三个数的和对 k 取模的范围是 0 到 2k)。

    • 对于每个 x,枚举两个余数 a 和 b,计算第三个余数 c=x−a−b。把题目转化为a%k有k种取值,b%k也有k种取值,而选定a、b之后,可以通过a、b、x计算出c,所以只需要枚举a%k和b%k即可,计算复杂度是O(k**2),能通过100%的测试。

    • 检查 c 是否合法(即 c 在 0 到 k−1 之间)。

    • 如果合法,计算当前组合的和,并更新最大值。

  5. 输出结果

    • 输出满足条件的最大和。


关键逻辑详解

  1. 按模数分类

    • 使用二维数组 m 记录每个余数对应的最大三个数。

    • 例如,m[y][0] 存储余数为 y 的最大数,m[y][1] 存储次大数,m[y][2] 存储第三大数。

  2. 枚举可能的和

    • 由于最多选三个数,三个数的和对 k 取模的范围是 0 到 2k。

    • 对于每个可能的和 x,枚举两个余数 a 和 b,计算第三个余数 c=x−a−b。

    • 检查 c是否合法(即 c在 0 到 k−1 之间)。

  3. 计算当前组合的和

    • 使用 m[a][0] 获取余数为 a 的最大数。

    • 使用 m[b][a==b] 获取余数为 b 的数:

      • 如果 a==b,则选择次大数 m[b][1]。

      • 否则,选择最大数 m[b][0]。

    • 使用 m[c][(a==c)+(b==c)]获取余数为 c 的数:

      • 如果 a==c或 b==c,则需要跳过已选择的数。

  4. 详细解析:m[a][0]

    • 表示余数为 a 的最大数。

    • 例如,如果 a = 1,则 m[1][0] 是余数为 1 的最大数。

  5. m[b][a == b]

    • 表示余数为 b 的数。

    • 如果 a == b,说明余数为 b 的数已经被选过一次(作为 m[a][0]),因此需要选择次大数 m[b][1]

    • 如果 a != b,则选择最大数 m[b][0]

  6. m[c][(a == c) + (b == c)]

    • 表示余数为 c 的数。

    • 如果 a == c 或 b == c,说明余数为 c 的数已经被选过,因此需要跳过已选择的数。

    • (a == c) + (b == c) 的值可能是 0、1 或 2:

      • 如果是 0,选择最大数 m[c][0]

      • 如果是 1,选择次大数 m[c][1]

      • 如果是 2,选择第三大数 m[c][2]

  7. max(ans, ...)

    • 将当前组合的和与 ans 比较,取较大值更新 ans

  8. 更新最大值

    • 使用 max 函数更新当前最大值。

相关文章:

  • 2025-03-17 Unity 网络基础1——网络基本概念
  • 学习单片机需要多长时间才能进行简单的项目开发?
  • 鸿蒙应用开发--数据埋点的名称由来,发展脉络,典型场景,现代演进的无埋点和智能化埋点//学习时长数据埋点的实现--待更新
  • 如何在 GoLand 中设置默认项目文件夹
  • 树莓派学习:环境配置
  • 《基于深度学习的高分卫星图像配准模型研发与应用》开题报告
  • 基于Spring Boot的红色革命文物征集管理系统的设计与实现(LW+源码+讲解)
  • Java高频面试之集合-13
  • 【ACM 独立出版 | EI 快检索】2025年数据挖掘与项目管理国际研讨会 (DMPM 2025)
  • 如何使用MySQL快速定位慢SQL问题?企业级开发中常见业务场景中实际发生的例子,涉及分页查询问题。(二)
  • LLMs之CoTM:《Detecting misbehavior in frontier reasoning models》翻译与解读
  • Linux驱动学习笔记(零)
  • [设计模式与源码]1_Spring三级缓存中的单例模式
  • 设计模式(行为型)-状态模式
  • Leetcode 刷题笔记1 单调栈part01
  • UART转AHB模块ModelSim仿真
  • C语言每日一练——day_10
  • 冒泡排序:古老算法中的智慧启示
  • c++学习系列----003.写文件
  • MySQL——数据类型
  • 解放日报社论:只争朝夕、不负重托,加快建成具有全球影响力的科技创新高地
  • 宋徽宗《芙蓉锦鸡图》亮相,故宫首展历代动物绘画
  • 发布亮眼一季度报后,东阿阿胶股价跌停:现金流隐忧引发争议
  • 宁波银行一季度净利74.17亿元增5.76%,不良率持平
  • 油电同智,安全超充!从上海车展看中国汽车产业先发优势
  • 王一博赛车故障退赛冲上热搜,工作室回应:下次再战