UVA - 11768 Lattice Point or Not (扩展欧几里得)

求一条线段上有多少个整点。

是道扩欧基础题,列出两点式方程,然后分四种情况讨论即可。但细节处理较多很容易写挫(某zzWA了十几发才过掉的)。

由于数据精度较小,浮点数比较没有用eps,直接==比较了。

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4 typedef long long ll;
 5
 6 void exgcd(ll a,ll b,ll& x,ll& y,ll& g) {
 7     if(!b)x=1,y=0,g=a;
 8     else exgcd(b,a%b,y,x,g),y-=x*(a/b);
 9 }
10
11 ll solve(double x1,double y1,double x2,double y2) {
12     if(x1>x2||(x1==x2&&y1>y2))swap(x1,x2),swap(y1,y2);
13     if(x1==x2&&y1==y2) {
14         if(x1==round(x1)&&x2==round(x2))return 1;
15         else return 0;
16     } else if(x1==x2) {
17         if(x1==round(x1))return floor(y2)-ceil(y1)+1;
18         else return 0;
19     } else if(y1==y2) {
20         if(y1==round(y1))return floor(x2)-ceil(x1)+1;
21         else return 0;
22     } else {
23         ll a=round((y2-y1)*100),b=round((x1-x2)*100),c=round((y2*x1-y1*x2)*100);
24         ll x,y,g;
25         exgcd(a,b,x,y,g);
26         if(c%g==0) {
27             x*=c/g;
28             ll bb=abs(b/g);
29             ll xl=ceil(x1),xr=floor(x2);
30             ll xll=x+(xl-x)/bb*bb;
31             ll xrr=x+(xr-x)/bb*bb;
32             if(xll<xl)xll+=bb;
33             if(xrr>xr)xrr-=bb;
34             return max(0ll,(xrr-xll)/bb+1);
35         } else return 0;
36     }
37 }
38
39 int main() {
40     ll T;
41     scanf("%lld",&T);
42     while(T--) {
43         double x1,y1,x2,y2;
44         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
45         printf("%lld\n",solve(x1,y1,x2,y2));
46     }
47     return 0;
48 }

原文地址:https://www.cnblogs.com/asdfsag/p/10354003.html

时间: 2024-10-27 06:32:32

UVA - 11768 Lattice Point or Not (扩展欧几里得)的相关文章

UVa 11768 格点判定(扩展欧几里得求线段整点)

https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后对于扩展欧几里得有了全面的了解. 根据两点式公式求出直线 ,那么ax+by=c 中的a.b.c都可以确定下来了. 接下来首先去计算出一组解(x0,y0),因为根据这一组解,你可以写出它的任意解,其中,K取任何整数. 需要注意的是,这个 a' 和 b' 是很重要的,比如说 b' ,它代表的是x每隔 b

UVA 11768 - Lattice Point or Not(数论)

UVA 11768 - Lattice Point or Not option=com_onlinejudge&Itemid=8&page=show_problem&category=516&problem=2868&mosmsg=Submission+received+with+ID+13823461" target="_blank" style="">题目链接 题意:给定两个点,构成一条线段.这些点都是十分

UVA 11768 Lattice Point or Not

扩展欧几里得,给两个点,就可以求出直线方程为 (yy-y)*x0 + (x-xx)*y0 = x*yy - y*xx,求的是在线段上的整点个数.所以就是(yy-y)*10*x0 + (x-xx)*10*y0 = x*yy - y*xx满足条件的解的个数.用exgcd搞之后求出一个解,再求出在线段上第一个整点的位置,然后再求有多少个在线段上的点. exgcd有点忘了,还有就是特殊情况的判断(比如平行坐标轴),另外就是不能交换输入点,输入 1.0 0.3 0.3 10.0交换后就是0.3 0.3 1

UVA 12169 Disgruntled Judge 枚举+扩展欧几里得

题目大意:有3个整数 x[1], a, b 满足递推式x[i]=(a*x[i-1]+b)mod 10001.由这个递推式计算出了长度为2T的数列,现在要求输入x[1],x[3],......x[2T-1], 输出x[2],x[4]......x[2T]. T<=100,0<=x<=10000. 如果有多种可能的输出,任意输出一个结果即可. 由于a和b都小于等于10000,直接枚举a和b暴力可以过.但是有没有更快的方法呢? 首先令递推式的i=2,那么x[2]=(a*x[1]+b)mod 1

UVA 10090 Marbles(扩展欧几里得)

Marbles Input: standard input Output: standard output I have some (say, n) marbles (small glass balls) and I am going to buy some boxes to store them. The boxes are of two types: Type 1: each box costs c1 Taka and can hold exactly n1 marbles Type 2:

【UVA】12169-Disgruntled Judge(暴力or欧几里得)

可能由于后台数据的原因,这道题直接暴力枚举a,b进行判断也能过,不过跑的时间长,效率太差了. 14021006 12169 Disgruntled Judge Accepted C++ 0.876 2014-08-11 08:46:28 不说了,比较无脑. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #incl

【扩展欧几里得】BZOJ1477-青蛙的约会

一直在WA,后来我发现我把东西看反了-- [题目大意] 给出一个长度为L的环状坐标轴,两个点开始时位于(X,0).(Y,0).每次两点分别往右边移动m和n,问能否相遇? [思路] 由题意,可得: X+mt=Y+nt(mod L) (X+mt)-(Y+nt)=L*k (n-m)t+L*k=X-Y. 可以用扩展欧几里得来做.具体来说,显然要满足n-m和L的最大公约数(记为d)要整除X-Y,否则无解.这个可以在扩展欧几里得中求出. 式子可以化简为:[(n-m)/d]*t+(L/d)*k=(X-Y)/d

POJ 1061 青蛙的约会 扩展欧几里得

扩展欧几里得模板套一下就A了,不过要注意刚好整除的时候,代码中有注释 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; ll exgcd(ll a, ll b, ll&x, ll&y) { if (b ==

POJ 2115 (模线性方程 -&gt; 扩展欧几里得)

题意: for(i=A ; i!=B ;i +=C)循环语句,问在k位操作系统中循环结束次数. 若在有则输出循环次数. 否则输出死循环. 存在这样的情况:i= 65533 :i<=2:i+= 4:时i = 2: 由模线性方程->扩展欧几里得 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using