LightOJ - 1077 How Many Points? 最大公约数(线段经过整点个数与gcd 证明)

题意:

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

思路:

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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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;
}




你可能感兴趣的:(数学,GCD)