菜比要靠div3上蓝,,,
题意
给出(n)个整数((n)是偶数),构造一个正整数(k),每次操作你可以把某个数减(k),要求构造的(k)能够使得至少一半的数最终相等,求最大的(k)。若(k)能无限大,输出-1。
最多10组数据,(4le n le 40),(-1e6le 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
", (*rit).first, (*rit).second);
if ((*rit).second >= n/2-m) {
ans = max(ans, (*rit).first);
//if (ans == 8) {
//printf("i == %d
", i);
//break;
//}
}
}
}
printf("%d
", ans);
}
return 0;
}