https://codeforces.com/contest/1598/problem/C
定义一个数组 \(\{a_i\}\)的 \(mean\) 为 \(\frac{\sum{a_i}}{n}\),给定一个数组,问有多少个有序对 \((i,j), i\leq j\),使得去掉 \(a_i, a_j\)后数组的 \(mean' = mean\)
这题题面有毒,一开始理解成了数组的 \(gcd\) 不变,而且除法是数学除法,带余数的那种
在理解了正确题意下来考虑这道题:
假设原数组的和为 \(sum\) ,原数组的 \(mean\) 为 \(k\),那么一定有 \(nk = sum\)。
现在去掉两个数,数组的和变为 \((n-2)k\),因此被减去的两数之和为 \(2sum/n\),显然如果 \(2sum \mod n != 0\) 则不存在解。
接下来就可以枚举 \(a_i+a_j\) 的数对个数,题解说这是一个经典问题,可以用 map 保存每个值出现了多少次,则对于值 \(a,\ 2sum/n-a\) 对答案的贡献即为 \(cnt[a]*\ cnt[2sum/n-a]\), 如果 \(a,\ 2sum/n-a\) 两值相等,那么答案需要--,最后再去重除2即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using DB = double;
using ll = long long;
using PII = pair<int, int>;
const int N = 2e5 + 10;
const ll INF = 1e18;
#define endl '\n'
int n = 2, m;
int a[N];
int st[6][1005], cntt[6];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n;
ll sum = 0;
map<int, int> cnt;
for (int i = 0, x; i < n; i++) {
cin >> a[i];
sum += a[i];
cnt[a[i]]++;
}
if (2 * sum % n != 0) {
cout << 0 << endl;
continue;
}
ll res = 2 * sum / n, ans = 0;
for (int i = 0; i < n; i++) {
int x = a[i];
int y = res - x;
ans += cnt[y];
if (x == y)
ans--;
}
cout << ans / 2 << endl;
}
return 0;
}