Power Transmission (Hard Edition)(几何)
题目链接:
https://codeforces.com/problemset/problem/1163/C2
题目大意:
有n个点,然后这些点直线都可以互相连线,然后问你有多少对直线是相交的。
题解:https://codeforces.com/blog/entry/66943
具体思路:
首先,我们可以将直线转换成这种形式 a*x - b*y = c.然后当前的点是(x1,y1)和(x2,y2)。我们此时的系数分别是 a = ( y2 - y1 ) , b = ( x2 - x1 ) , c= (x1 * y2 - x2 *y1).
注意化式子的时候为了保证正确性,我们可以使得a的系数都是正的,然后如果a的系数是0的话,我们再保证b是正的,这样会避免成比例成相反数的情况。
注意去重的时候,如果两个式子的表达式完全一样,那么这个式子应该只算一个。如果已经存在当前斜率相同的,但是为平行关系,我们这个时候应该计算总的合法边数 - 和当前边斜率相等边数。
AC代码:
1 #include<iostream>
2 #include<map>
3 #include<string>
4 #include<cstring>
5 #include<bits/stdc++.h>
6 using namespace std;
7 # define inf 0x3f3f3f3f
8 # define ll long long
9 const ll mod = 998244353;
10 const int maxn = 2e3+100;
11 struct node
12 {
13 int x,y;
14 } q[maxn];
15 struct Line
16 {
17 int a,b,c;
18 Line() {}
19 Line(int xx,int yy,int zz)
20 {
21 a=xx,b=yy,c=zz;
22 }
23 } line[maxn];
24 //map<pair<int,int>,int>cnt;
25 //map<pair<int,int>,bool>repat;
26 map<pair<int,int>,set<int> >vis;
27 int main()
28 {
29 int n;
30 scanf("%d",&n);
31 for(int i=1; i<=n; i++){
32 scanf("%d %d",&q[i].x,&q[i].y);
33 }
34 ll ans=0,tot=0;
35 for(int i=1; i<=n; i++)
36 {
37 for(int j=i+1; j<=n; j++)
38 {
39 int t1 = q[j].y-q[i].y;
40 int t2 = q[j].x-q[i].x;
41 int t3 = q[i].x*q[j].y-q[j].x*q[i].y;
42 int tmp=__gcd(t1,t2);
43 t1/=tmp,t2/=tmp;
44 if(t1<0||(t1==0&&t2<0))// 注意系数
45 t1=-t1,t2=-t2;
46 tmp=t2*q[i].y-t1*q[i].x;
47 if(vis[make_pair(t1,t2)].count(tmp)==0)
48 {
49 tot++;
50 vis[make_pair(t1,t2)].insert(tmp);
51 ans+=tot-vis[make_pair(t1,t2)].size();
52 }
53 }
54 }
55 printf("%lld\n",ans);
56 return 0;
57 }