解题思路
题目要求找出一个最大的子集,使得其中任意两个数的和都不能被 整除。关键发现:
- 如果两个数的和能被
整除,那么它们对
的余数之和也能被
整除
- 对于余数为
的数,最多只能选一个
- 对于余数为
的数(当
为偶数时),最多只能选一个
- 对于其他余数
,要在
和
中选择数量较多的那组
解题思路:
- 统计每个余数出现的次数
- 分类讨论:
- 余数为0的情况
为奇数时的情况
为偶数时的情况
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, K;
cin >> N >> K;
// 读取数组并统计余数
vector<int> remainderCount(K);
for (int i = 0; i < N; i++) {
int num;
cin >> num;
remainderCount[num % K]++;
}
// 计算最大子集大小
int result = 0;
// 处理余数为0的情况
if (remainderCount[0] > 0) {
result++;
}
// 处理其他余数
if (K % 2 == 1) {
// K为奇数
for (int i = 1; i <= (K-1)/2; i++) {
result += max(remainderCount[i], remainderCount[K-i]);
}
} else {
// K为偶数
for (int i = 1; i < K/2; i++) {
result += max(remainderCount[i], remainderCount[K-i]);
}
// 处理K/2的情况
if (remainderCount[K/2] > 0) {
result++;
}
}
cout << result << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
// 统计余数出现次数
int[] remainderCount = new int[K];
for (int i = 0; i < N; i++) {
int num = sc.nextInt();
remainderCount[num % K]++;
}
// 计算最大子集大小
int result = 0;
// 处理余数为0的情况
if (remainderCount[0] > 0) {
result++;
}
// 处理其他余数
if (K % 2 == 1) {
// K为奇数
for (int i = 1; i <= (K-1)/2; i++) {
result += Math.max(remainderCount[i], remainderCount[K-i]);
}
} else {
// K为偶数
for (int i = 1; i < K/2; i++) {
result += Math.max(remainderCount[i], remainderCount[K-i]);
}
// 处理K/2的情况
if (remainderCount[K/2] > 0) {
result++;
}
}
System.out.println(result);
}
}
# 读取输入
N, K = map(int, input().split())
nums = list(map(int, input().split()))
# 统计余数出现次数
remainder_count = [0] * K
for num in nums:
remainder_count[num % K] += 1
# 计算最大子集大小
result = 0
# 处理余数为0的情况
if remainder_count[0] > 0:
result += 1
# 处理其他余数
if K % 2 == 1:
# K为奇数
for i in range(1, (K-1)//2 + 1):
result += max(remainder_count[i], remainder_count[K-i])
else:
# K为偶数
for i in range(1, K//2):
result += max(remainder_count[i], remainder_count[K-i])
# 处理K/2的情况
if remainder_count[K//2] > 0:
result += 1
print(result)
算法及复杂度
- 算法:余数定理 + 贪心
- 时间复杂度:
-
为数组长度,只需要遍历一次数组
- 空间复杂度:
- 需要一个大小为
的数组存储余数计数