[Codeforces Round #748 (Div. 3)](https://codeforces.com/contest/1593) D2 Half of Same

菜比要靠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;
}
原文地址:https://www.cnblogs.com/YjmStr/p/15417471.html