线段上的整点数

题目链接:https://codeforces.com/contest/1036/problem/E

思路:学会了一个在线段上的整数点等于 GCD(x1 - x2, y1 - y2) +  1,然后去重线段相交的重复整点。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const double eps = 1e-8;
 5 const int maxn = 1e3 +5 ;
 6 int sgn(double x)
 7 {
 8     if(fabs(x) < eps) return 0;
 9     else return x < 0 ? -1 : 1;
10 }
11 struct Point{
12     double x, y;
13     Point(){}
14     Point(double _x, double _y){
15         x = _x, y = _y;
16     }
17     void input(){
18         scanf("%lf%lf", &x, &y);
19     }
20     bool operator == (Point b) const{
21         return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
22     }
23     bool operator < (Point b)const{
24         return sgn(x - b.x) == 0 ? sgn(y - b.y < 0) : x < b.x;
25     }
26     Point operator - (const Point &b)const{
27         return Point(x - b.x, y - b.y);
28     }
29     double operator ^(const Point &b){
30         return x * b.y - y * b.x;
31     }
32     double operator *(const Point &b){
33         return x * b.x + y * b.y;
34     }
35 };
36 struct Line{
37     Point s, e;
38     Line(){}
39     Line(Point _s, Point _e){s = _s, e = _e;}
40     bool operator == (Line v){
41         return (s == v.s) && (e == v.e);
42     }
43     void input(){
44         s.input();
45         e.input();
46     }
47     int segcrossing(Line v)
48     {
49         int d1 = sgn((e - s)^(v.s - s));
50         int d2 = sgn((e - s)^(v.e - s));
51         int d3 = sgn((v.e - v.s)^(s - v.s));
52         int d4 = sgn((v.e - v.s)^(e - v.s));
53         if( (d1^d2) == -2 && (d3^d4) == -2 )return 2;
54         return (d1 == 0 && sgn((v.s - s)*(v.s - e)) <= 0) ||
55         (d2 == 0 && sgn((v.e - s)*(v.e - e)) <= 0) ||
56         (d3 == 0 && sgn((s - v.s)*(s - v.e))<=0) ||
57         (d4 == 0 && sgn((e - v.s)*(e - v.e))<=0);
58     }
59     Point crosspoint(Line v){
60         double a1 = (v.e - v.s)^(s - v.s);
61         double a2 = (v.e - v.s)^(e - v.s);
62         return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1));
63     }
64 };
65 Line l[maxn];
66 int main()
67 {
68     std::ios::sync_with_stdio(false);
69     int n;
70     cin >> n;
71     ll ans = 0;
72     int x1, x2, y1, y2;
73     for(int i = 0;i < n;i++){
74         cin >> x1 >> y1 >> x2 >> y2;
75         l[i] = Line(Point((double)x1, (double)y1), Point((double)x2, (double)y2));
76         ans += __gcd(abs(x1 - x2), abs(y1 - y2)) + 1;
77     }
78     for(int i = 0;i < n;i++)
79     {
80         set< pair<int, int> >st;
81         for(int j = i + 1;j < n;j++)
82         {
83             if(l[i].segcrossing(l[j])){
84                 Point v = l[i].crosspoint(l[j]);
85                 if((int)v.x == v.x && (int)v.y == v.y)
86                     st.insert({v.x,v.y});
87             }
88         }
89         ans -= st.size();
90     }
91     cout << ans << endl;
92     return 0;
93 }

猜你喜欢

转载自www.cnblogs.com/Carered/p/11531154.html