P7676 COCI2013-2014#5 TROKUTI

P7676 COCI2013-2014#5 TROKUTI - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

首先考虑三角形的形成条件(注意到题面保证了无三线共点):

  • 三条边;
  • 任意两条边不平行。

考虑补集,统计存在两条边平行的三元组数量,用总数 \(\dbinom{n}{3}\) 减去即可。

存在两条边平行,也就是满足以下两种情况之一:

  • 两条边平行,另一条边不与这两条边平行;
  • 三条边均平行。

两条直线平行当且仅当它们的斜率相同(竖线可看做 \(+\infty\)),那么我们统计每种斜率出现的数量 \(c\)

我们对于每种斜率都进行如下统计:

  • \(c \ge 2\) 时,数量 \(\dbinom{c}{2} \times (n - c)\),代表在斜率为 \(c\) 的这些平行直线中选取两条,和另外一条与其斜率不同的直线组成的三元组数量;
  • \(c \ge 3\) 时,可以构成满足条件二的三角形,数量 \(\dbinom{c}{3}\),代表斜率为 \(c\) 的这些平行直线中选取三条组成的三元组数量。

这样每个不合法的三元组都可以被不重不漏统计一次。

至于如何统计每种斜率出现的数量,应该采用 map。

时间复杂度 \(\mathcal{O}(n \log V)\)\(V\)\(a_i, b_i\) 的值域。

当然我这里采用的是记录 gcd 约分后的 \(a_i, b_i\) 的方法,如果直接记录斜率的实数值时间复杂度可以达到 \(\mathcal{O}(n\log n)\)

#include <bits/stdc++.h>
#define int long long
inline int read() {
    int x = 0;
    bool flag = true;
    char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == '-')
            flag = false;
        ch = getchar();
    }
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    if(flag)
        return x;
    return ~(x - 1);
}

const int mod = (int)1e9 + 7;
const int maxn = 300005;

int a[maxn], b[maxn];

inline int C3(int x) {
    return x * (x - 1) / 2 * (x - 2) / 3;
}

inline int C2(int x) {
    return x * (x - 1) / 2;
}

int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}

typedef std :: pair <int, int> pii;
std :: map <pii, int> m;

signed main() {
    int n = read();
    for (int i = 1; i <= n; ++i) {
        int a = read(), b = read();
        read();
        
        if (a == 0)
            b = 1;
        else if (b == 0)
            a = 1;
        else {
            int d = gcd(a, b);
            a /= d;
            b /= d;
        }

        ++m[std :: make_pair(a, b)];
    }

    int ans = C3(n) % mod;
    for (auto it : m) {
        int cnt = it.second;
        if (cnt >= 2)
            ans -= C2(cnt) * (n - cnt) % mod;
        if (cnt >= 3)
            ans -= C3(cnt) % mod;
        (ans += mod) %= mod;
    }

    printf("%lld\n", ans);
    return 0;
}
posted @ 2022-10-29 01:56  dbxxx  阅读(42)  评论(0编辑  收藏  举报