CodeForces - 1163C2 Power Transmission (Hard Edition)(分数表示y=kx+b)
题目大意
给你n个点问他们组成的直线有多少对相交。
解题思路
这题如果用直线的点斜式的话很好做,可以用分数来表示斜率和截距,然后利用任意两个不同斜率的直线必定相交来求解,注意分子分母都要化到最简形式。
代码
const int maxn = 1e3+10;
const int maxm = 1e6+10;
int n;
P cdt[maxn];
map<P, set<P>> mp;
set<int> st1, st2;
int main() {
cin >> n;
for (int i = 1; i<=n; ++i) cin >> cdt[i].x >> cdt[i].y;
for (int i = 1; i<=n; ++i)
for (int j = i+1; j<=n; ++j) {
int kup = cdt[i].y-cdt[j].y;
int kdown = cdt[i].x-cdt[j].x;
if (!kup) st1.insert(cdt[i].y);
else if (!kdown) st2.insert(cdt[i].x);
else {
int g = __gcd(kup, kdown);
kup /= g, kdown /= g;
int bup = cdt[i].y*kdown-kup*cdt[i].x;
int bdown = kdown;
g = __gcd(bup, bdown);
bup /= g, bdown /= g;
mp[{kup, kdown}].insert({bup, bdown});
}
}
ll sum = st1.size()+st2.size();
for (auto v : mp) sum += v.second.size();
ll ans = (sum-st1.size())*st1.size() + (sum-st2.size())*st2.size();
for (auto v : mp) ans += (sum-v.second.size())*v.second.size();
cout << ans/2 << endl;
return 0;
}