CF1598C Delete Two Elements


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;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM