[CodeForces-1036E] Covered Points 暴力 GCD 求交点

  题意:

    在二维平面上给出n条不共线的线段,问这些线段总共覆盖到了多少个整数点

  

  解法:

      用GCD可求得一条线段覆盖了多少整数点,然后暴力枚举线段,求交点,对于相应的

    整数交点,结果-1即可

  

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<vector>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 using namespace std;
 11 #define eps 1e-6
 12 #define For(i,a,b) for(int i=a;i<=b;i++)
 13 #define Fore(i,a,b) for(int i=a;i>=b;i--)
 14 #define lson l,mid,rt<<1
 15 #define rson mid+1,r,rt<<1|1
 16 #define mkp make_pair
 17 #define pb push_back
 18 #define sz size()
 19 #define met(a,b) memset(a,b,sizeof(a))
 20 #define iossy ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
 21 #define fr freopen
 22 #define pi acos(-1.0)
 23 #define Vector Point
 24 typedef pair<int,int> pii;
 25 const long long linf=1LL<<62;
 26 const int iinf=1<<30;
 27 const double dinf=1e17;
 28 const int Mod=1e9+9;
 29 typedef long long ll;
 30 typedef long double ld;
 31 const int maxn=1000005;
 32 int n;
 33 struct Point{
 34     ll x,y;
 35     int id;
 36     Point(ll x=0,ll y=0):x(x),y(y) {}
 37     Point operator - (const Point &a)const { return Point(x-a.x,y-a.y);}
 38     bool operator == (const Point &a)const { return x==a.x && y==a.y; }
 39 };
 40 ll Cross(Vector a,Vector b){
 41     return a.x*b.y-a.y*b.x;
 42 }
 43 ll Dot(Vector a,Vector b) {
 44     return a.x*b.x+a.y*b.y;
 45 }
 46 bool onsg(Point p,Point a1,Point a2){
 47     return Cross(a1-p,a2-p)==0 && Dot(a1-p,a2-p)<0;
 48 }
 49 void ck(ll &c){
 50     if(c>0) c=1;
 51     else if(c<0) c=-1;
 52 }
 53 int Ins(Point a1,Point a2,Point b1,Point b2){
 54     if(a1==b1 || a1==b2 || a2==b1 || a2==b2) return 1;
 55     if(onsg(a1,b1,b2) || onsg(a2,b1,b2) || onsg(b1,a1,a2) || onsg(b2,a1,a2)) return 1;
 56     ll c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1);
 57     ll c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
 58     ck(c1);ck(c2);ck(c3);ck(c4);
 59     return c1*c2<0 && c3*c4<0;
 60 }
 61 set<pair<ll,ll> >c;
 62 void chk(Point p,Vector v,Point q,Vector w){
 63     Vector u=p-q;
 64     ll v1=Cross(w,u),v2=Cross(v,w);
 65     if(abs(v1*v.x)%v2!=0 || abs(v1*v.y)%v2!=0) return ;
 66     ll xx,yy;
 67     xx=p.x+v.x*v1/v2;yy=p.y+v.y*v1/v2;
 68     c.insert(mkp(xx,yy));
 69 }
 70 struct segm{
 71     Point p1,p2;
 72 };
 73 segm ss[maxn];
 74 Point p1,p2;
 75 void solve(){
 76     iossy;
 77     cin>>n;
 78     int ans=0;
 79     For(i,1,n){
 80         cin>>p1.x>>p1.y>>p2.x>>p2.y;
 81         ss[i].p1=p1;ss[i].p2=p2;
 82         ans+=__gcd(abs(ss[i].p2.x-ss[i].p1.x),abs(ss[i].p2.y-ss[i].p1.y))+1;
 83     }
 84     For(i,1,n){
 85         c.clear();
 86         For(j,i+1,n){
 87             int ct=Ins(ss[i].p1,ss[i].p2,ss[j].p1,ss[j].p2);
 88             if(ct) chk(ss[i].p1,ss[i].p2-ss[i].p1,ss[j].p1,ss[j].p2-ss[j].p1);
 89         }
 90         ans-=c.sz;
 91     }
 92     //cout<<ans-c.sz<<endl;
 93     cout<<ans<<endl;
 94 }
 95 int main(){
 96     int t=1;
 97    // For(i,1,t) printf("Case #%d: ",i);
 98     solve();
 99     return 0;
100 }

原文地址:https://www.cnblogs.com/cjbiantai/p/9611034.html

时间: 2024-10-11 16:48:22

[CodeForces-1036E] Covered Points 暴力 GCD 求交点的相关文章

Codeforces 1000C Covered Points Count

C. Covered Points Count题目大意:有n条线段,问有多少个点被i条线段覆盖(i=1~n).很常见的线段覆盖套路题QAQ.坐标排序后把左端点当做+1,右端点当做-1,扫一遍统计答案即可.但是记得开ll,数组大小开双倍. 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <queue> 6 #

EDU 50 E. Covered Points 利用克莱姆法则计算线段交点

E. Covered Points 利用克莱姆法则计算线段交点.n^2枚举,最后把个数开方,从ans中减去. ans加上每个线段的定点数, 定点数用gcs(△x , △y)+1计算. #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include

Educational Codeforces Round 46 C - Covered Points Count

C - Covered Points Count emmm 好像是先离散化一下 注意 R需要+1 这样可以确定端点 emmm 扫描线?瞎搞一下? #include<bits/stdc++.h> using namespace std; #define maxn 4000005 #define LL long long LL a[maxn],b[maxn],ll[maxn],rr[maxn],c[maxn]; LL x[maxn],y[maxn]; vector<LL >q; int

线段求交点的算法

算法一: 求两条线段所在直线的交点, 再判断交点是否在两条线段上. 求直线交点时 我们可通过直线的一般方程 ax+by+c=0 求得(方程中的abc为系数,不是前面提到的端点,另外也可用点斜式方程和斜截式方程,此处暂且不论). 然后根据交点的与线段端点的位置关系来判断交点是否在线段上. 公式如下图: 算法一思路比较清晰易懂, 但是性能并不高. 因为它在不确定交点是否有效(在线段上)之前, 就先去计算了交点, 耗费了较多的时间. 如果最后发现交点无效, 那么之前的计算就白折腾了. 而且整个计算的过

暴力法求最小生成树

暴力法求最小生成树 5 71 2 22 5 21 3 41 4 73 4 12 3 13 5 6 我们采用的是dfs的回溯暴力,所以对于如下图,只能搜索到3条路,就是那种dfs的路. 思路: 暴力求最小生成树求这个图的最小生成树我就要看有多少个点被选进去了,vis数组就好,并且用个n来表示已经被选的点的个数 然后记录所以已经选了的路径和 1 #include <bits/stdc++.h> 2 #define INFINITE 0x3fffffff 3 using namespace std;

Codeforces 347B - Fixed Points

题意:给定一个序列,现有一种操作:两个数的位置互换.问最多操作一次,序列 [元素位置i]  与 [元素Ai] 相等的最多个数? 根据题意,最多个数为 : [操作之前[元素位置i]  与 [元素Ai] 相等的个数] +  [调换两个 [元素位置i]  与 [元素Ai] 不相等 的元素 使某个 [元素位置i]  与 [元素Ai] 相等的个数]. 举个例子: 0 1 2 4 3 这个序列,调换后面两个元素,正好使每个 [元素位置i]  与 [元素Ai] 相等. 也就是说,调换的时候,不用考虑 [元素位

N个数GCD求解法

[N个数GCD求解法] 1.质因数分解法. 2.两两求解法. 3.更相减损法. 例题 4.Trick1. 5.Trick2. 6.Trick3.

&lt;笔试&gt;&lt;面试&gt;C/C++单链表相关(4)判断两链表是否相交,求交点(链表不带环/可能带环)

判断两链表是否相交,求交点(假设链表不带环) 判断两链表是否相交,求交点(假设链表可能带环) RingEntry_Point()等函数见前篇. SListNode* Intersect(SListNode *&L, SListNode *&M)//判断两链表是否相交,求交点(假设链表不带环) {  //思路:若不带环,只有相交/不想交两种情况  // 与RingEntry_Point()函数方法相同:  //     求两个链表长度之差K,再令一个指针从长链表开始先走K步,令另一个指针从短

Codeforces 57C Array dp暴力找规律

题目链接:点击打开链接 先是计算非递增的方案, 若非递增的方案数为x, 则非递减的方案数也是x 答案就是 2*x - n 只需求得x即可. 可以先写个n3的dp,然后发现规律是 C(n-1, 2*n-1) 然后套个逆元即可. #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll long long #def