【洛谷 P1170】兔八哥与猎人 题解(数学+辗转相除法)

兔八哥与猎人

题目描述

兔八哥躲藏在树林旁边的果园里。果园有 M × N M \times N M×N 棵树,组成一个 M M M N N N 列的矩阵,水平或垂直相邻的两棵树的距离为 1 1 1。兔八哥在一棵果树下。

猎人背着猎枪走进了果园,他爬上一棵果树,准备杀死兔八哥。

如果猎人与兔八哥之间没有其它的果树,猎人就可以看到兔八哥。

现己知猎人和兔八哥的位置,编写程序判断兔子所在的位置是否安全.

输入格式

第一行为 n n n,表示有 n n n 组数据,每组数据的第一行为两个正整数 a x a_x ax a y a_y ay,表示猎人的位置,第二行为两个正整数 b x b_x bx b y b_y by,表示兔八哥的位置。

输出格式

共有 n n n 行,每行为 yesno 表示兔八哥的位置是否安全。

样例 #1

样例输入 #1

1
1 1
1 2

样例输出 #1

no

提示

1 ≤ n ≤ 1 0 5 1\le n \le 10^5 1n105 1 ≤ a x , a y , b x , b y ≤ 1 0 8 1 \le a_x, a_y, b_x, b_y \le 10^8 1ax,ay,bx,by108


思路

我们可以将两个整数 x x x y y y 看作是一个二维平面上的点 ( x , y ) (x, y) (x,y)。如果两点之间存在一个整数点,那么必然是一个整数倍的关系,即存在两个整数 k k k l l l,使得 x = k z x=kz x=kz y = l z y=lz y=lz,其中 z z z x x x y y y 的最大公约数。因此, x / z x/z x/z y / z y/z y/z 必然不互质。反之,如果 x / z x/z x/z y / z y/z y/z 不互质,则存在两个整数 k k k l l l,使得 x = k z x=kz x=kz y = l z y=lz y=lz,因此它们之间必然存在一个整数点。

因此,我们只需要计算出 ∣ x − a ∣ |x-a| xa ∣ y − b ∣ |y-b| yb 的最大公约数,判断是否为 1 1 1 即可。

注意:输入没有给出 M M M N N N 列,地图视为无限大。


AC代码

#include 
#define AUTHOR "HEX9CF"
using namespace std;

// 辗转相除法
int gcd(int x, int y)
{
    if (x < y)
    {
        x ^= y ^= x ^= y;
    }
    if (!y)
    {
        return x;
    }
    return gcd(y, x % y);
}

int abs(int x)
{
    return (x < 0) ? (-x) : x;
}

int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        // 猎人位置
        int a, b;
        // 兔子位置
        int x, y;
        cin >> a >> b >> x >> y;
        if (gcd(abs(x - a), abs(y - b)) != 1)
        {
            // 不互质,有整数点
            cout << "yes" << endl;
        }
        else
        {
            cout << "no" << endl;
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构与算法,算法,c++)