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

[蓝桥杯]倍数问题

倍数问题

题目描述

众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 nn 个数,希望你从这 nn 个数中找到三个数,使得这三个数的和是 KK 的倍数,且这个和最大。数据保证一定有解。

输入描述

第一行包括 2 个正整数 n, Kn, K。

第二行 nn 个正整数,代表给定的 nn 个数。

其中,1≤n ≤105, 1≤K ≤1031≤n ≤105, 1≤K ≤103,给定的 nn 个数均不超过 108108。

输出描述

输出一行一个整数代表所求的和。

输入输出样例

示例

输入

4 3
1 2 3 4

输出

9

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

总通过次数: 2649  |  总提交次数: 4259  |  通过率: 62.2%

难度: 困难   标签: 2018, 构造, 省赛

算法思路

题目要求从n个数中选取三个数,使其和为K的倍数且和最大。关键挑战在于n最大可达10^5,直接枚举所有组合(O(n³))会超时。我们采用​​余数分组优化策略​​:

  1. ​余数分组​​:将每个数按模K的余数分组,同一余数组保留最大的三个数(因为最多取三个)
  2. ​组合枚举​​:枚举两个余数i和j,第三个余数t由公式计算:t = (K - (i+j)%K) % K
  3. ​分组取数​​:
    • 若三余数不同:每组取最大值
    • 若两余数相同:从该组取两个最大值
    • 若三余数相同:取组内三个最大值
  4. ​和最大化​​:对每种合法组合计算和并更新最大值

​复杂度分析​​:O(K²) = 1000² = 10⁶,满足1s时限

算法演示代码实现(C++)

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n, K;cin >> n >> K;vector<vector<long long>> groups(K); // 余数分组// 分组预处理:保留每组最大的三个数for (int i = 0; i < n; ++i) {long long x;cin >> x;int r = x % K;groups[r].push_back(x);if (groups[r].size() > 3) {sort(groups[r].begin(), groups[r].end(), greater<long long>());groups[r].pop_back();}}// 组内排序(降序)for (int i = 0; i < K; ++i) {if (!groups[i].empty()) {sort(groups[i].begin(), groups[i].end(), greater<long long>());}}long long ans = LLONG_MIN;// 枚举余数组合for (int i = 0; i < K; ++i) {for (int j = 0; j < K; ++j) {int t = (K - (i+j) % K) % K; // 计算第三个余数if (groups[i].empty() || groups[j].empty() || groups[t].empty())continue;// 1. 三余数相同if (i == j && j == t) {if (groups[i].size() >= 3) {long long sum = groups[i][0] + groups[i][1] + groups[i][2];ans = max(ans, sum);}} // 2. i和j相同else if (i == j) {if (groups[i].size() >= 2) {long long sum = groups[i][0] + groups[i][1] + groups[t][0];ans = max(ans, sum);}}// 3. i和t相同else if (i == t) {if (groups[i].size() >= 2) {long long sum = groups[i][0] + groups[i][1] + groups[j][0];ans = max(ans, sum);}}// 4. j和t相同else if (j == t) {if (groups[j].size() >= 2) {long long sum = groups[j][0] + groups[j][1] + groups[i][0];ans = max(ans, sum);}}// 5. 三余数不同else {long long sum = groups[i][0] + groups[j][0] + groups[t][0];ans = max(ans, sum);}}}cout << ans << endl;return 0;
}

代码解析

  1. ​分组预处理(L12-20)​

    • 计算每个数的余数r = x % K
    • 每组只保留最大的三个数(插入后排序并移除最小值)
  2. ​组内排序(L23-27)​

    • 对每组数据降序排序,确保[0]是最大值
  3. ​余数组合枚举(L33-34)​

    • 双重循环枚举余数ij
    • 公式t = (K - (i+j)%K) % K确保三数和为K倍数
  4. ​组合验证(L36-68)​

    • ​三余数相同​​:需要组内≥3个数(取前三)
    • ​两余数相同​​:从相同组取两个最大值
    • ​余数不同​​:每组取最大值
    • 更新最大和ans

实例验证

​输入​​分组​​组合​​输出​​结果​
4 3 [1,2,3,4]0:[3] 1:[4,1] 2:[2]3+4+2=99
5 5 [5,5,5,5,5]0:[5,5,5]5+5+5=1515
3 10 [8,15,25]8:[8] 5:[15] 5:[25]8+15+25=4848

注意事项

  1. ​整数溢出​​:使用long long存储和(最大3×10⁸)
  2. ​边界情况​​:
    • K=1时:所有余数为0,取最大的三个数
    • 组内元素不足:如三余数相同时需检查元素数量
  3. ​去重处理​​:同一组内取多个数时需取不同位置的数
  4. ​负余数处理​​:C++的%运算可能返回负余数,需调整:
    int r = (x % K + K) % K; // 确保余数在[0,K-1]

测试点设计

​测试类型​​输入数据​​预期输出​​验证重点​
基本功能4 3 [1,2,3,4]9标准流程
全相同数5 5 [5,5,5,5,5]15同组取多值
大数测试3 1000 [1e8,1e8,1e8]3e8溢出处理
边界值3 1 [10,20,30]60K=1处理
分散余数5 4 [8,7,6,5,4]19 (7+6+6?)最优组合
负余数3 5 [-9,10,14]15 (-9+10+14)余数调整

优化建议

  1. ​分组结构优化​

    // 使用优先队列维护每组最大值(自动排序)
    vector<priority_queue<long long>> groups(K);
    groups[r].push(x);
    if (groups[r].size() > 3) groups[r].pop();
  2. ​枚举顺序优化​

    for (int i = 0; i < K; ++i) {for (int j = i; j < K; ++j) { // j从i开始避免重复int t = (2*K - i - j) % K; // 等价计算
  3. ​提前终止​

    // 若当前组最大值×3 < 现有ans,跳过该组
    if (groups[i][0]*3 < ans) continue;
  4. ​哈希缓存​

    // 对小型分组(|group|<3)预计算可能组合
    unordered_map<int, vector<long long>> cache;
http://www.lryc.cn/news/2401615.html

相关文章:

  • 定时任务的 cron 表达式
  • 【MySQL】 约束
  • MySQL 的 redo log 和 binlog 区别?
  • 前端vue打开多个窗口,关闭窗口后才继续执行后续逻辑
  • 「深度拆解」Spring Boot如何用DeepSeek重构MCP通信层?从线程模型到分布式推理的架构进化
  • 如何避免在前端项目中出现重复的第三方依赖包?
  • Java开发中复用公共SQL的方法
  • 【西门子杯工业嵌入式-2-点亮一颗LED】
  • 代码随想录算法训练营第60期第五十五天打卡
  • 重磅更新! 基于Gemini 2.5 Pro打造的AI智能体PlantUML-X上线!
  • [5-02-04].第01节:Jmeter环境搭建:
  • AI智能推荐实战之RunnableParallel并行链
  • windows server2019 不成功的部署docker经历
  • Gemini开源项目DeepResearch:基于LangGraph的智能研究代理技术原理与实现
  • React状态管理Context API + useReducer
  • 【无标题】路径着色问题的革命性重构:拓扑色动力学模型下的超越与升华
  • Doris Catalog 联邦分析查询性能优化:从排查到优化的完整指南
  • 01 Deep learning神经网络的编程基础 二分类--吴恩达
  • 视频自动化分割方案:支持按时间与段数拆分
  • Open SSL 3.0相关知识以及源码流程分析
  • 股指期货合约价值怎么算?
  • 【QT】使用QT帮助手册找控件样式
  • 计算机网络(5)——数据链路层
  • VuePress完美整合Toast消息提示
  • JVM 调优参数详解与实践
  • adb 连不上真机设备问题汇总
  • [yolov11改进系列]基于yolov11引入注意力机制SENetV1或者SENetV2的python源码+训练源码
  • 鸿蒙仓颉语言开发实战教程:商城搜索页
  • 上门服务小程序会员系统框架设计
  • 图像去雾数据集总汇