菜比要靠div3上蓝,,,
题意
给出\(n\)个整数(\(n\)是偶数),构造一个正整数\(k\),每次操作你可以把某个数减\(k\),要求构造的\(k\)能够使得至少一半的数最终相等,求最大的\(k\)。若\(k\)能无限大,输出-1。
最多10组数据,\(4\le n \le 40\),\(-1e6\le a_i \le 1e6, \sum n \le 100\)
题解
如果没有\(n/2\)的限制而是全部相等,只需要求出每个数和最小的数的差值求gcd即可。
考虑枚举前\(n/2\)小的数中的某一个作为最终要等于的数。处理出比它大的数和它的差值,分解因子并去重,记录出现次数。随后从最大的因子开始枚举,若某个因子出现了超过\(n/2\)次,直接break,这个因子即为当前枚举的数的答案,复杂度通过去重保证。(因子个数一定不超过2e6)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 40 + 7;
#define ll long long
int n, m, tot, a[maxn];
int rd() {
int s = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {s = s * 10 + c - '0'; c = getchar();}
return s * f;
}
map<int, int> fac[maxn], cnt;
int b[maxn];
int main() {
int T = rd();
while (T--) {
m = 0;
int ans = -1;
n = rd();
for (int i = 1; i <= n; i++) {
a[i] = rd();
fac[i].clear();
}
cnt.clear();
sort(a+1, a+n+1);
for (int i = 1; i <= n; i++)
cnt[a[i]]++;
for (map<int, int> :: iterator it = cnt.begin(); it != cnt.end(); it++) {
if ((*it).second >= n/2) {
puts("-1");
m = -114514;
break;
}
}
if (m == -114514) continue;
m = 0;
for (int i = 1; i <= n / 2 + 1; i++) {
tot = m = 0;
for (int j = i; j <= n; j++) {
if (a[j] == a[i]) {
m++;
continue;
}
b[++tot] = a[j] - a[i];
}
for (int j = 1; j <= tot; j++) {
for (int k = 1; k * k <= b[j]; k++) {
if (b[j] % k == 0) {
fac[i][k]++;
if (k * k != b[j])
fac[i][b[j]/k]++;
}
}
}
for (map<int, int> :: reverse_iterator rit = fac[i].rbegin(); rit != fac[i].rend(); rit++) {
//printf("%d %d\n", (*rit).first, (*rit).second);
if ((*rit).second >= n/2-m) {
ans = max(ans, (*rit).first);
//if (ans == 8) {
//printf("i == %d\n", i);
//break;
//}
}
}
}
printf("%d\n", ans);
}
return 0;
}