题解 P8398 [CCC2022 S4] Good Triplets

显然,答案不好直接求,我们考虑用总数减去不合法的方案数。

为了不算重,我们每次只考虑当前点与圆心连线交圆周于一点所形成的半圆内的不合法情况,然后用组合数算出剩下两个点的选择方案数。

我们可以用前缀和记录区间内点的数量,然后对于一个点可以算出它的对称点,两段区间拼起来就可以算出半圆内的点数。

最后还要减去退化的三角形,一种是三个点在同一位置,另一种是有两个点在同一位置。

值得注意的是,如果周长为奇数,对称点以及半圆的划分会略有不同,需要特判一下。

复杂度线性。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
ll n, c, a[N], sum[N], ans, cnt[N];
ll getnum(ll w, ll w2) { //计算区间内点的数量 
    ll num;
    if (w2 > w) num = sum[c - 1] - sum[w2 - 1] + sum[w];
    else {
        if (w2 > 0) num = sum[w] - sum[w2 - 1];
        else num = sum[w];
    }
    return num;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n >> c;
    ans = n * (n - 1) * (n - 2) / 6; //总数 
    for (int i = 1; i <= n; ++i) cin >> a[i], ++sum[a[i]], ++cnt[a[i]];
    for (int i = 1; i < c; ++i) sum[i] += sum[i - 1];
    for (int i = 1; i <= n; ++i) {
        ll w = a[i], w2, num;
        w2 = (w + c / 2) % c; //对称点 
        if (c % 2) w2 = (w2 + 1) % c;
        num = getnum(w, w2);
        num -= cnt[w];
        ans -= num * (num - 1) / 2;
    }
    for (int i = 0; i < c; ++i) { //减去退化的三角形 
        if (cnt[i] >= 3) ans -= cnt[i] * (cnt[i] - 1) * (cnt[i] - 2) / 6; //三点重合 
        if (cnt[i] >= 2) { //两点重合 
            ll w = i, w2 = (i + c / 2) % c, num;
            if (c % 2) w2 = (w2 + 1) % c;
            num = getnum(w, w2);
            if (c % 2 == 0) {
                num -= cnt[w] + cnt[w2];
                ans -= cnt[i] * (cnt[i] - 1) / 2 * num;
            } else {
                num -= cnt[w];
                ans -= cnt[i] * (cnt[i] - 1) / 2 * num;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

本文作者:HQJ2007

本文链接:https://www.cnblogs.com/HQJ2007/p/17561276.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   HQJ2007  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起