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

[蓝桥杯]倍数问题

倍数问题

题目描述

众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。现在小葱给了你 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;

相关文章:

  • ZooKeeper 安装教程(Windows + Linux 双平台)
  • 26考研 | 王道 | 计算机组成原理 | 三、存储系统
  • [蓝桥杯]堆的计数
  • 2023年全国研究生数学建模竞赛华为杯A题WLAN网络信道接入机制建模求解全过程文档及程序
  • function call到MCP技术演进
  • 44、web实验-后台管理系统基本功能
  • 使用 minicom 录制串口报文并回放
  • 黑马Java面试笔记之 并发编程篇(线程池+使用场景)
  • c++算法学习4——广度搜索bfs
  • 如何做好一份技术文档?(上篇)
  • Java 实现下拉框树状结构接口的核心思路
  • 设计模式(代理设计模式)
  • openGauss数据库备份与恢复实践
  • Python中的self参数介绍
  • Cilium动手实验室: 精通之旅---6.Cilium IPv6 Networking and Observability - Lab
  • ROS2里面与话题 /move_base_simple/goal 和 /move_base/status 相对应的话题名字及其含义
  • 基于SSM框架的医院电子病历管理系统,分为用户网页和管理后台,包括科室模块、医生模块、预约挂号模块、就诊记录模块、就诊评价模块、轮播图模块和系统基础模块
  • 【PhysUnits】15.15 变量类型(variable.rs)
  • 【SSM】SpringBoot学习笔记1:SpringBoot快速入门
  • 链表相关知识
  • 高大上强企业网站/江苏营销型网站建设
  • 炫酷的移动端网站/免费推广自己的网站
  • wordpress 禁用feed/seo需要培训才能找到工作吗
  • 互联网趋势发展前景/网站关键词优化排名怎么做
  • 有什么网站可以做名片/西安网站定制开发
  • 网站怎样优化文章关键词/青岛疫情最新情况