题面
原题链接:计蒜客T1271
思路
我真的问了大佬好久也查了好久。。我 tcl QWQ
这个题很难直接枚举,不过可以考虑能构成完美子数组的几种情况:
1:数组里所有元素都能被K整除且数组长度至少为2
2:k为偶数时,数组里所有元素都对K取模的结果都是K/2,且数组长度至少为2;这样数组里任意两个数的和都是k的倍数
3:可用map 或 set记录某个余数是否出现过
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <vector>
using namespace std;
map<int, bool> r; //用于记录这个数的余数是否出现过
int main()
{
int n, k, a;
cin >> n >> k;
if (n < 2) //如果不够两个数字 直接输出-1并结束
{
cout << "-1" << endl;
return 0;
}
//分情况统计
int b=0, c=0, sum = 0;
for (int i = 1; i <= n; i++)
{
cin >> a;
if (a % k == 0)
b++; //统计能被k整除的数有多少
if (a % k == k / 2)
c++; //统计能被k/2整除但不能被k整除的数有多少
if (r[a % k] == 0) //如果不能被k整除也不能被k/2整除 就看看余数是否标记过
{
r[k - a % k] = 1; //把需要补齐的余数标记 eg a=7,k=5. a%k==2 那就把5-2=3 即k-a%k标记
}
else
{
sum = 2; //如果标记过了 那就代表已经有一个可以与它组成一对的数了。就至少有2个了
}
}
int ans;
if (k % 2 == 0) //如果k是偶数 那么不能被k整除 能被k/2整除的任意两个数组合 相加的和是k的倍数
{
if (sum == 0 && b < 2 && c < 2) //三种情况都不符合
cout << "-1" << endl;
else
{
ans = max(sum, max(b, c));//求三种情况的最大值(最长子序列)
cout << ans << endl;
}
}
else //k不是偶数的时候不存在被k/2整除的情况
{
if(sum==0&&b<2)
cout << "-1" << endl;
else
{
ans = max(b, sum);//求两种情况的最大值
cout << ans << endl;
}
}
}