取模游戏
描述
在盲盒中有n个纸条,每个纸条有一个数字x,我可以任选两张纸条,我有一种能力可以看清盒子中所有纸条的数字,我想要我拿出的两个数字之和对mod取模最大,你能帮我算出我能拿出的数字之和对mod取模最大是多少吗?
输入
第一行两个整数n 和 mod,代表有n张纸条以及一个模数 mod
第二行n个整数表示每张纸上的数字 x
输出
一个整数x 表示拿出的两个数个数之和对 mod 取模的最大值
输入样例 1
5 10
1 1 1 2 1
输出样例 1
3
3<=n<=2e5
1<=mod<=998244353
1<=x<=1e12
这个问题可以通过计算所有可能的两个数字之和,然后对这些和取模,最后找出最大值来解决。但是,这个问题有一个更简单的解决方案,基于模运算的性质。
给定模数mod,我们可以观察到,对于任意两个数字a和b,如果a + b大于mod,那么(a + b) mod mod等于(a mod mod + b mod mod) mod mod。这意味着,我们只需要考虑每个数字对mod取模后的结果,然后找出两个数,它们的和对mod取模后是最大的。
这个问题的关键在于理解,对于任意的整数a和b,(a mod mod + b mod mod) mod mod等于(a + b) mod mod。因此,我们只需要考虑每个纸条上的数字对mod取模后的结果。
算法步骤如下:
创建一个空列表mods,用于存储每个数字对mod取模后的结果。
遍历输入的n个整数,将每个数字对mod取模的结果添加到mods列表中。
对mods列表进行排序。
从后向前遍历排序后的mods列表,找出第一个不是列表中最大元素的数字。
计算这两个数字(列表中的最大元素和找到的非最大元素)的和,并对mod取模。
输出计算出的和。
下面是这个算法的伪代码实现:
#include <iostream>
#include <vector>
#include <algorithm> // 用于 std::sort
using namespace std;
int main() {
int n, mod;
cin >> n >> mod;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
// 对每个数字进行 mod 运算,并将结果存入新的 vector 中
vector<int> mods;
for (int num : nums) {
mods.push_back(num % mod);
}
// 对 mod 结果进行排序
sort(mods.begin(), mods.end());
// 找出最大的两个不同数字,计算它们的和对 mod 取模的结果
int maxMod = mods.back(); // 排序后的最大值
int maxSumMod = 0;
for (int i = mods.size() - 1; i > 0; --i) {
if (mods[i] != maxMod) {
maxSumMod = (maxMod + mods[i]) % mod;
break;
}
}
cout << maxSumMod << endl;
return 0;
}