P7676 COCI2013-2014#5 TROKUTI
P7676 COCI2013-2014#5 TROKUTI - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
首先考虑三角形的形成条件(注意到题面保证了无三线共点):
- 三条边;
- 任意两条边不平行。
考虑补集,统计存在两条边平行的三元组数量,用总数
存在两条边平行,也就是满足以下两种情况之一:
- 两条边平行,另一条边不与这两条边平行;
- 三条边均平行。
两条直线平行当且仅当它们的斜率相同(竖线可看做
我们对于每种斜率都进行如下统计:
时,数量 ,代表在斜率为 的这些平行直线中选取两条,和另外一条与其斜率不同的直线组成的三元组数量; 时,可以构成满足条件二的三角形,数量 ,代表斜率为 的这些平行直线中选取三条组成的三元组数量。
这样每个不合法的三元组都可以被不重不漏统计一次。
至于如何统计每种斜率出现的数量,应该采用 map。
时间复杂度
当然我这里采用的是记录 gcd 约分后的
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】