题目链接:https://codeforces.com/contest/1163/problem/C2
题解:最多有n*(n-1)条直线,可以暴力的去枚举判断直线是否相交,同一平面内的两条直线不平行即相交,所以将所有的直线按斜率划分,相同斜率中去掉重复的直线,每个斜率的贡献就是:该斜率的直线数*(总的直线数(不算重合的)-该斜率的直线数)。
感觉这道题主要是让我学了下pair和map的用法,还有代码中截距的计算,题解是整型,但我没想通,感觉应该是double才对,但不知道万一出精度锅怎么办。。
#include<bits/stdc++.h>
#define ll long long
#define pr pair<ll, ll>
using namespace std;
const int maxn = 1e3+5;
struct Point{
ll x, y;
}p[maxn];
map<pr, ll>cnt;
map<pair<pr, double>, bool>vis;
int main(){
int n;
cin >> n;
for(int i = 0; i < n; i++){
cin >> p[i].x >> p[i].y;
}
ll m = 0;
cnt.clear();
vis.clear();
for(int i = 0; i < n; i++){
for(int j = i+1; j < n; j++){
ll a = p[i].y - p[j].y;
ll b = p[i].x - p[j].x;
double c = 1.0*(p[i].y*p[j].x - p[i].x*p[j].y);
ll d = __gcd(a, b);
a /= d;
b /= d;
c /= d*1.0;
if(a < 0 || (a == 0 && b < 0)){
a = -a, b = -b, c = -c;
}
pr tmp = make_pair(a, b);
if(!vis[make_pair(tmp, c)]){//去掉重合的直线
vis[make_pair(tmp, c)] = true;
cnt[tmp]++;
m++;//统计总的直线数
}
}
}
map<pr, ll>::iterator it;
ll ans = 0;
for(it = cnt.begin(); it != cnt.end(); it++){
ll tmp = cnt[it->first];
ans += tmp * (m-tmp);
}
ans /= 2;
cout << ans << endl;
}