题目链接
题目描述
小红从原点 出发,可以进行四种移动:
- 向上移动
步
- 向下移动
步
- 向左移动
步
- 向右移动
步 问她是否能通过若干次移动到达目标点
。
解题思路
这个问题可以分解为两个独立的一维问题:一个是在 轴上的移动,另一个是在
轴上的移动。
1. Y 轴方向的移动
在 轴上,小红可以向上移动
或向下移动
。假设她向上移动了
次,向下移动了
次,那么她最终的
坐标就是
。
这是一个线性丢番图方程。根据裴蜀定理(Bézout's identity),对于方程 ,它有整数解
的充要条件是
是
的倍数。
应用到本题中, 坐标能达到的所有位置集合就是
,即所有
的整数倍。
因此,要想到达目标 坐标,必须满足
是
的倍数,即
。
2. X 轴方向的移动
同理,在 轴上,小红可以向右移动
或向左移动
。假设她向右移动了
次,向左移动了
次,最终的
坐标就是
。
根据裴蜀定理, 坐标能达到的所有位置集合是所有
的整数倍。
因此,要想到达目标 坐标,必须满足
是
的倍数,即
。
综合结论
小红能到达目标点 的充要条件是,
坐标和
坐标都必须能独立到达。所以,必须同时满足以下两个条件:
是
的倍数。
是
的倍数。
我们对 和
取绝对值是因为移动方向是双向的,能到达
就一定能到达
。
代码
#include <iostream>
#include <cmath>
#include <numeric>
#include <utility>
using namespace std;
// 手动实现 gcd 以确保兼容性
long long custom_gcd(long long a, long long b) {
while (b) {
a %= b;
swap(a, b);
}
return a;
}
void solve() {
long long x, y, a, b, c, d;
cin >> x >> y >> a >> b >> c >> d;
// 检查 y 坐标的可达性
bool y_reachable = (abs(y) % custom_gcd(a, b) == 0);
// 检查 x 坐标的可达性
bool x_reachable = (abs(x) % custom_gcd(c, d) == 0);
if (x_reachable && y_reachable) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
import java.util.Scanner;
public class Main {
// 辗转相除法求最大公因数
public static long gcd(long a, long b) {
while (b != 0) {
long temp = a % b;
a = b;
b = temp;
}
return a;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
long x = sc.nextLong();
long y = sc.nextLong();
long a = sc.nextLong();
long b = sc.nextLong();
long c = sc.nextLong();
long d = sc.nextLong();
boolean y_reachable = (Math.abs(y) % gcd(a, b) == 0);
boolean x_reachable = (Math.abs(x) % gcd(c, d) == 0);
if (x_reachable && y_reachable) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
}
import math
def solve():
x, y, a, b, c, d = map(int, input().split())
# 检查 y 坐标的可达性
y_reachable = (abs(y) % math.gcd(a, b) == 0)
# 检查 x 坐标的可达性
x_reachable = (abs(x) % math.gcd(c, d) == 0)
if x_reachable and y_reachable:
print("YES")
else:
print("NO")
t = int(input())
for _ in range(t):
solve()
算法及复杂度
- 算法:数论、裴蜀定理、最大公约数
- 时间复杂度:对于每组测试数据,主要计算两次最大公约数。辗转相除法的时间复杂度为
。因此,总时间复杂度为
。
- 空间复杂度:
。