10402: C.机器人
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 56 Solved: 21
[ Submit][ Status][ Web Board]
Description
Dr. Kong 设计的机器人卡尔非常活泼,既能原地蹦,又能跳远。由于受软硬件设计所限,机器人卡尔只能定点跳远。若机器人站在(X,Y)位置,它可以原地蹦,但只可以在(X,Y),(X,-Y),(-X,Y),(-X,-Y),(Y,X),(Y,-X),(-Y,X),(-Y,-X)八个点跳来跳去。
现在,Dr. Kong想在机器人卡尔身上设计一个计数器,记录它蹦蹦跳跳的数字变化(S,T),即,路过的位置坐标值之和。
你能帮助Dr. Kong判断机器人能否蹦蹦跳跳,拼出数字(S,T)吗?
假设机器人卡尔初始站在(0,0)位置上。
Input
第一行: K 表示有多少组测试数据。
接下来有K行,每行:X Y S T
1≤K≤10000 -2*109 <= X , Y, S, T <= 2*109
数据之间有一个空格。
Output
对于每组测试数据,输出一行:Y或者为N,分别表示可以拼出来,不能拼出来
Sample Input
3
2 1 3 3
1 1 0 1
1 0 -2 3
Sample Output
Y
N
Y
思路:设num[i]为第i个位置路过的次数。
则有
(num[1]*x + num[2]*x - num[3]*x - num[4]*x + num[5]*y + num[6]*y - num[7]*y - num[8]*y) = s.
(num[1]*y - num[2]*y + num[3]*y - num[4]*y + num[5]*x - num[6]*x + num[7]*x - num[8]*y) = t.
变量太多,不好搞,考虑能否去掉几个 或者 将若干个变量表示为一个变量。
发现
num[1]*x - num[4]*x + ... = s
num[1]*y - num[4]*y + ... = t
可以合并(num[1]-num[4])为一个变量 cnt[1].
同理(x, -y) (-x, y) -> (num[2] - num[3]) = cnt[2].
(y, x) (-y, -x) -> (num[5] - num[8]) = cnt[3] .
(y, -x) (-y, x) -> (num[6] - num[7]) = cnt[4]。
那么直接有
cnt[1] * x + cnt[2] * x + cnt[3] * y + cnt[4] * y = s.
cnt[1] * y - cnt[2] * y + cnt[3] * x - cnt[4] * x = t.
化简有
(cnt[1]+cnt[2]) * x + (cnt[3]+cnt[4]) * y = s.
(cnt[1]-cnt[2]) * y + (cnt[3]-cnt[4]) * x = t.
可以用exgcd求出A = (cnt[1]+cnt[2]), B = (cnt[3]+cnt[4]), C = (cnt[1]-cnt[2]), D = (cnt[3]-cnt[4])。
条件——A + C 和 B + D是偶数。
求出通解A、B、C、D后,以A C举例,A0 = A + i * (y / gcd(x, y)), C0 = C - j * (x / gcd(x, y))。
我们考虑b-a*x奇偶性的判定,其中a、b是定值,x不定。x为偶数时,a*x一定是偶数。反之x为奇时就取决于定值x。
抛开不沾边的,就是说在若只考虑奇偶性,那么只需处理两种情况。x为偶数时处理0、x为奇数时处理1。
我们枚举i、j(0 <= i, j <= 1),看是否满足即可。
最后注意特判 x = 0, y = 0 的情况。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#define CLR(a, b) memset(a, (b), sizeof(a))
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
const int MOD = 1e9+7;
const int MAXN = 500+10;
const int MAXM = 200000;
const int INF = 0x3f3f3f3f;
void add(LL &x, LL y) {x += y; x %= MOD;}
void exgcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if(b == 0) {d = a, x = 1, y = 0;}
else
{
exgcd(b, a%b, d, y, x);
y -= x * (a / b);
}
}
int main()
{
int t; scanf("%d", &t);
while(t--)
{
LL x, y, s, t;
scanf("%lld%lld%lld%lld", &x, &y, &s, &t);
if(x == 0 && y == 0)
{
if(s == 0 && t == 0)
printf("Y\n");
else
printf("N\n");
continue;
}
LL a, b, d;
exgcd(x, y, d, a, b);
if(s % d || t % d) {
printf("N\n");
continue;
}
LL A, B, C, D;
A = s / d * a;
B = s / d * b;
C = t / d * a;
D = t / d * b;
bool flag = false; LL AA, BB, CC, DD;
for(int i = 0; i <= 1; i++)
{
AA = A + 1LL * i * (y / d); BB = B - 1LL * i * (x / d);
for(int j = 0; j <= 1; j++) {
CC = C - 1LL * j * (x / d), DD = D + 1LL * j * (y / d);
//printf("%lld %lld %lld %lld\n", AA, BB, CC, DD);
if((AA + CC) % 2 == 0 && (BB + DD) % 2 == 0)
flag = true;
if(flag) break;
}
if(flag) break;
}
printf(flag ? "Y\n" : "N\n");
}
return 0;
}