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;
}
posted @ 2021-03-06 10:32  shuitiangong  阅读(74)  评论(0编辑  收藏  举报