题意 :
- 给一序列,每次操作可以让一个元素减去k(k>=1),求最大的k使得若干次操作后序列中至少一半元素相等,若k为任意大,则输出-1
思路 :
- 首先枚举任意两个数的差,那么答案k一定存在于这些差的因数中,所以枚举每组差的因数,以当前差的被减数为媒介(最终至少一半数等于这个数)判断当前k是否满足条件,取满足的最大值
- 特别地,当原序列中有一个元素已经大于等于元素的个数的一半(n为奇数是(n+1)/2,n为偶数是n/2,但由于向下取整,可以统一为(n+1)/2),那么k为任意大,输出-1
#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>
#define debug(a) cout << #a << " = " << a << endl; // 调试
#define x first
#define y second
using namespace std;
typedef long long ll;
const int N = 50;
int n;
int a[N];
int update(int dif, int x)
{
int k = 0;
for (int i = 1; i * i <= dif; i ++ )
{
if (dif % i) continue;
int cnt = 0;
for (int j = 1; j <= n; j ++ )
if (abs(a[j] - x) % i == 0) cnt ++ ;
if (cnt >= (n + 1) / 2) k = max(k, i);
cnt = 0;
for (int j = 1; j <= n; j ++ )
if (abs(a[j] - x) % (dif / i) == 0) cnt ++ ;
if (cnt >= (n + 1) / 2) k = max(k, dif / i);
}
return k;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int _;
cin >> _;
while (_ -- )
{
unordered_map<int, int> ma;
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i], ma[a[i]] ++ ;
bool flag = false;
for (auto i : ma)
if (i.second >= (n + 1) / 2)
{
flag = true;
break;
}
if (flag)
{
cout << -1 << endl;
continue;
}
int k = 0;
for (int i = 1; i <= n; i ++ )
for (int j = i + 1; j <= n; j ++ )
{
int dif = abs(a[i] - a[j]);
if (dif == 0) continue; // k>=1
k = max(k, update(dif, a[i]));
// debug(dif)debug(k) // 调试
}
cout << k << endl;
}
return 0;
}