zzuoj 10402: C.机器人 【数论 exgcd】

来源:互联网 发布:stateserver 端口 编辑:程序博客网 时间:2024/06/05 18:01

10402: C.机器人

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 56  Solved: 21
[Submit][Status][Web Board]

Description

Dr. Kong 设计的机器人卡尔非常活泼,既能原地蹦,又能跳远。由于受软硬件设计所限,机器人卡尔只能定点跳远。若机器人站在(XY)位置,它可以原地蹦,但只可以在(XY),(X-Y),(-XY),(-X-Y),(YX),(Y-X),(-YX),(-Y-X)八个点跳来跳去。

现在,Dr. Kong想在机器人卡尔身上设计一个计数器,记录它蹦蹦跳跳的数字变化(ST),即,路过的位置坐标值之和。

你能帮助Dr. Kong判断机器人能否蹦蹦跳跳,拼出数字(ST)吗?

假设机器人卡尔初始站在(00)位置上。

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


0 0
原创粉丝点击