#质因数分解 #枚举 因为答案肯定在 $[0,2\times 10^6]$ 这个区间里面,因此我们可以考虑枚举所有可能的答案并逐一校验。检验时,我们可以枚举 $i$ 让其他 $j\ne i$ 的 $a_j$ 都改变成 $a_i$。时间复杂度为 $\mathcal O(kn^2)$,但是由于 $k$ 达到了 $2\times 10^6$,因此会超时。 考虑优化校验复杂度。能够发现,当 $a_j>a_i$ 的时候,只需要除可能解的余数一样就行了。因此,我们可以新建一个表用来存余数对应的数量,找到一个数量大于等于 $n/2$ 的余数。时间复杂度为 $\mathcal O(kn)$,仍然超时。 这次,我们不再寻找解了,而是枚举 $a_i$ 找到最优解。对于所有 $a_j>a_i$ 的 $a_j$,都可以通过一个数 $x$ 满足 $(a_j-a_i)\bmod x=0$ 减到 $a_i$,也就是说可能的 $x$ 必须是 $a_j-a_i$ 的因数。因此,我们先求出所有的因数,存进 [[map]] 里面,再找到一个最大的因数 $x$ 满足 $x$ 的数量大于等于 $n/2$ 就行了。时间复杂度 $\mathcal O(n^2\sum\limits_{i=1}^{n}\sqrt{a_i})$。 ```cpp #include <iostream> #include <unordered_set> #include <unordered_map> #include <algorithm> #include <vector> using namespace std; const int kMaxN = 45; int a[kMaxN], t, n, ans; vector<int> v; unordered_map<int, int> f; unordered_set<int> calc(int x) { unordered_set<int> s; for (int i = 1; i * i <= x; i++) { if (x % i == 0) { s.insert(i); s.insert(x / i); } } return s; } int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); for (cin >> t; t; t--) { cin >> n; ans = -1e9; for (int i = 1; i <= n; ++i) { cin >> a[i]; } sort(a + 1, a + n + 1); // 枚举要变成的 for (int i = 1; i <= n; i++) { // 清空 int times = 0; f.clear(); v.clear(); // 枚举其他的数 for (int j = 1; j <= n; j++) { if (a[j] == a[i]) { // 如果大小一样 times++; // 记录数量 } else if (a[j] > a[i]) { // 大于 a[i] v.push_back(a[j] - a[i]); // 加入 vector } } // 如果一样的已经超过了 n/2 就有无数种解 if (times >= n / 2) { ans = 1e9; continue; } // 求因数并记录 for (int i : v) { for (int j : calc(i)) { f[j]++; } } // 找最大的答案 for (auto j : f) { if (j.second >= n / 2 - times) { ans = max(ans, j.first); } } } cout << (ans == 1e9 ? -1 : ans) << '\n'; } return 0; } ```