蓝桥杯 倍数构造 知识点:枚举优化

59 阅读2分钟

0倍数问题 - 蓝桥云课 (lanqiao.cn)

最开始的朴素做法只能通过样例:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, k;
int maxn = -1;

int main() {
	cin >> n >> k;
	for (int i = 0; i < n; i++)
		cin >> a[i];


	for (int i = 0; i + 2 < n; i++) {
		int sum = 0;
		sum += a[i] + a[i + 1] + a[i + 2];
		if (sum % k == 0) {
			maxn = max(maxn, sum);
		}
	}

	cout << maxn << endl;
	return 0;
}

image.png

image.png

原因在于题目要求找的是任意的满足i<j<k的a[i],a[j],a[k]之和,但是不是说a[i],a[j],a[k]一定是连续的三个数。

修正



#include <bits/stdc++.h>
using namespace std;
int n, K, maxn = 0;
int a[100010];

int main() {
	// 请在此输入您的代码
	cin >> n >> K;

	for (int i = 1; i <= n; i++)
		cin >> a[i];


	for (int i = 1; i <= n - 2; i++) {
		for (int j = i + 1; j <= n - 1; j++) {
			for (int k = j + 1; k <= n; k++) {
				int x = a[i] + a[j] + a[k];
				if (x % K == 0) {
					maxn = max(maxn, x);
				}
			}
		}
	}

	cout << maxn << endl;
	return 0;
}




因为n是1e5,三层循环,肯定会超一部分: image.png

优化

我们给数组降序排序,这样开头的就是最大的,我们也就可以更快的找到3个数之和是K的倍数的最大和,提高效率。

其次我们在遍历的时候不要傻傻遍历,如果我们发现某一项的和最大两项之和小于 maxn,那内层循环就不要再遍历了。

#include <bits/stdc++.h>
using namespace std;
int n, K, maxn = 0;
int a[100010];

int main() {
	cin >> n >> K;

	for (int i = 1; i <= n; i++)
		cin >> a[i];

	sort(a + 1, a + 1 + n, greater<int>());


	for (int i = 1; i <= n - 2; i++) {
		if (a[i] + a[1] + a[2] <= maxn)
			continue;
		for (int j = i + 1; j <= n - 1; j++) {
			if (a[i] + a[j] + a[1] <= maxn)
				continue;
			for (int k = j + 1; k <= n; k++) {
				int x = a[i] + a[j] + a[k];
				if (x % K == 0) {
					maxn = max(maxn, x);
				}
			}
		}
	}

	cout << maxn << endl;
	return 0;
}

image.png