LightOJ

来源:互联网 发布:软件测试培训课程 编辑:程序博客网 时间:2024/06/06 04:05

题意:

给定两个整点,求这段线段之间跨过的整点的个数

思路:

1,再纸上画一下就可以猜到了

2,证明一下:

设线段的两个端点为 (x1, y1) 和 (x2, y2)

我们都知道,要是这个线段经过某个整点(a,b)的话,我令 dx = (a - x1), dy =  (b - y1);必定有  dy / dx  =   (x2 - x1) / (y2 - y1) ①, 因为要满足相同的斜率

还能推出: dy / ( y2 - y1 ) = dx / (x2 - x1)—— ②;

假设这个整点是从(x1, y1)开始的第一个整点,然后我把这个 dx dy 叫做整点元(自己瞎取的),而且这个线段经过的所有两两相邻的整点,x y 差值也满足 dx dy;

要求经过整点的个数,就要求(x2 - x1) 和 (y2 - y1)的最大公约数 gcd , (x2 - x1) / gcd 和 (y2 - y1)/ gcd  就是我说的整点元 dx dy;

最后结果加上(x1, y1)这个点, 

注意数据范围


#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<set>#include<queue>#include<stack>#include<map>#define PI acos(-1.0)#define in freopen("in.txt", "r", stdin)#define out freopen("out.txt", "w", stdout)using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 1e6 + 7, maxd = 20 + 7, mod = 1e9 + 7;const int INF = 0x7f7f7f7f;int T;ll gcd(ll a, ll b) {    return b == 0 ? a : gcd(b, a%b);}int main() {    int T;    scanf("%d", &T);    for(int tt = 1; tt <= T; ++tt) {        ll a, b, c, d;        scanf("%lld %lld %lld %lld", &a, &b, &c, &d);        ll ans = gcd( abs(a-c), abs(b-d) );        printf("Case %d: %lld\n", tt, ans+1);    }    return 0;}




原创粉丝点击