倍数问题(2018蓝桥杯)
题目描述:
众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。
但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。
现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数,使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。
输入格式:
从标准输入读入数据。 第一行包括 2 个正整数 n, K。 第二行 n 个正整数,代表给定的 n 个数。
输出格式:
输出到标准输出。
输出一行一个整数代表所求的和。
示例:
输入: 4 3 1 2 3 4 输出: 9
数据约定:
对于 30% 的数据,n <= 100。 对于 60% 的数据,n <= 1000。 对于另外 20% 的数据,K <= 10。 对于 100% 的数据,1 <= n <= 10^5, 1 <= K <= 10^3,给定的 n 个数均不超过 10^8。 资源约定: 峰值内存消耗(含虚拟机) < 256M CPU消耗 < 1000ms 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。 注意: main函数需要返回0; 只使用ANSI C/ANSI C++ 标准; 不要调用依赖于编译环境或操作系统的特殊函数。 所有依赖的函数必须明确地在源文件中 #include <xxx> 不能通过工程设置而省略常用头文件。
题目分析:
本题可以使用暴力枚举,枚举分析所有的数,若分析得出结果值最大值输出;
但是若纯 暴力时间复杂度将会变得十分大,
所以可以先分析所有数据,只保留余数相同的最大的三个数。然后逐个枚举得出结果。
代码:
c++:
#pragma warning(disable:4996) #include<iostream> #include<memory> #include<vector> #include<unordered_map> typedef long long ll; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int main() { int i, num; int k, flag = 1; int b[1001][3];//用于判断余数相同的三个数 memset(b, -1, sizeof(b)); std::unordered_map<int, int>c;//map的key值存放余数,value值存放余数对应二维数组b的下标 scanf("%d %d", &i, &num); while (i--) { k = read(); int kk = k % num; if (!c[kk]) { c[k % num] = flag;//将余数所在的位置给map的映射 b[flag][0] = k; flag++; } else//若该余数有值,则替换其中最小值或者加入其中 { int inte = k; for (int z = 0;z < 3;z++) if (b[c[kk]][z] < inte) inte ^= b[c[kk]][z] ^= inte ^= b[c[kk]][z]; } } //枚举 ll ans = 0, v1, v2, v3; for (auto iter1 = c.begin();iter1 != c.end();iter1++) { for (auto iter2 = c.begin();iter2 != c.end();iter2++) { int mainder = (2 * num - iter1->first - iter2->first) % num; v1 = b[iter1->second][0]; if (iter1->first == iter2->first) { v2 = b[iter1->second][1]; if (iter1->first == mainder) v3 = b[iter1->second][2]; else v3 = b[mainder][0]; if (v3 == -1 || v2 == -1) continue; } else { v2 = b[iter2->second][0]; if (iter1->first == mainder) v3 = b[iter1->second][1]; else if (iter2->first == mainder) v3 = b[iter2->second][1]; else v3 = b[mainder][0]; if (v3 == -1 || v2 == -1) continue; } ll tem = v1 + v2 + v3; if (ans < tem)ans = tem; } } printf("%lld", ans); return 0; }