[HAOI2011]向量
Description
给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y)。
说明:这里的拼就是使得你选出的向量之和为(x,y)
Input
第一行数组组数t,(t<=50000)
接下来t行每行四个整数a,b,x,y (-2*10^9<=a,b,x,y<=2*10^9)
Output
t行每行为Y或者为N,分别表示可以拼出来,不能拼出来
Sample Input
3
2 1 3 3
1 1 0 1
1 0 -2 3
Sample Output
Y
N
Y
HINT
样例解释:
第一组:(2,1)+(1,2)=(3,3)
第三组:(-1,0)+(-1,0)+(0,1)+(0,1)+(0,1)=(-2,3)
Solution:
首先8种向量只有四个本质不同的向量。
我们设有
k1(a,b),k2(a,−b),k3(b,a),k4(b,−a)
,
那么我们有
a(k1+k2)+b(k3+k4)=x
,
a(k3−k4)+b(k1−k2)=y
,我们记
p1=k1+k2,p2=k3+k4,p3=k3−k4,p4=k1−k2
,那么
k1,k2,k3,k4
有整数解的条件是
p1≡p4(mod2),p2≡p3(mod2)
,我们用拓展欧几里得接出
p1,p2,p3,p4
的一组解,显然
mod2
将每一个不定方程分为两类,一共四种情况,一一判断即可
Code :
/*************************************************************************
> File Name: bzoj2299.cpp
> Author: Archer
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read(){
ll x = 0, f = 1; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {x = x * 10ll + ch - '0'; ch = getchar(); }
return f == 1 ? x : -x;
}
inline void exgcd(ll a, ll &x, ll b, ll &y){
if (b == 0) {x = 1ll; y = 0ll; return;}
ll x1, y1; exgcd(b, x1, a % b, y1);
x = y1; y = x1 - a / b * y1;
}
inline ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
inline bool check(ll p1, ll p2, ll p3, ll p4){
return (((p1-p4)%2 == 0) && ((p2-p3)%2 == 0));
}
int main(){
for (ll T = read(); T--;){
ll a = read(), b = read(), x = read(), y = read();
if (a < b) swap(a, b);
if (a == 0) {puts(x == 0 && y == 0 ? "Y" : "N"); continue;}
ll d = gcd(a, b); ll p1, p2, p3, p4, d1 = b / d, d2 = a / d;
if (x % d != 0 || y % d != 0) {puts("N"); continue;}
ll t1, t2; exgcd(a / d, t1, b / d, t2);
p1 = t1 * x / d; p2 = t2 * x / d;
p3 = t1 * y / d; p4 = t2 * y / d;
if (check(p1, p2, p3, p4) || check(p1 + d1, p2 - d2, p3, p4)
||check(p1, p2, p3 + d1, p4 - d2) || check(p1 + d1, p2 - d2, p3 + d1, p4 - d2)) puts("Y");
else puts("N");
}
return 0;
}