BZOJ 2299 向量

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 \le 50000)\)
接下来t行每行四个整数\(a,b,x,y\)(\(-2 \times10^{9} \le a,b,x,y \le 2 \times 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)\)

本题实际上有用的向量只有\((a,b),(b,a),(a,-b),(b,-a)\)(假设可以选负的)。
我们假设四个向量分别用了\(k_{1},k_{2},k_{3},k_{4}\)个,那么我们可以得到方程:$$(k_{1}+k_{3})a+(k_{2}+k_{4})b=x$$$$(k_{1}-k_{3})b+(k_{2}+k_{4})a=y$$
转变一下,我们令\(S = k_{1}+k_{3},T = k_{1}-k_{3},P = k_{2}+k_{4},Q = k_{2}+k_{4}\),于是有$$S \times a+P \times b = x$$$$T \times b+Q \times a = y$$
即存在合法的\(P,Q,S,T\)使得两个不定方程成立(\(S,T\)同奇偶,\(P,Q\)同奇偶(同奇偶后我们一定可以找到一组解使得\(P,Q\)相等))。
根据翡蜀定理,我们必定可以找到一组合法解满足\(Ax+By=gcd(A,B)\)\(A,B\)同奇偶,当且仅当\(A,B\)同奇或\(A,B\)同偶。
对于\(S,T,P,Q\)同偶的情况,即为$$2 \times gcd(a,b) \mid x $$$$2 \times gcd(a,b) \mid y$$
对于\(S,T,P,Q\)同奇的情况,即为$$2 \times gcd(a,b) \mid x-a-b$$$$2 \times gcd(a,b) \mid y-a-b$$
对于\(S,T\)同奇\(P,Q\)同偶的情况,即为$$2 \times gcd(a,b) \mid x-a$$$$2 \times gcd(a,b) \mid y-b$$
对于\(S,T\)同偶\(P,Q\)同奇的情况,即为$$2 \times gcd(a,b) \mid x-b$$$$2 \times gcd(a,b) \mid y-a$$
判一下即可。

#include<cstdio>
#include<cstdlib>
using namespace std;

long long d;

inline long long gcd(long long a,long long b) { return b?gcd(b,a%b):a; }
inline bool okay(long long a,long long b) { return !(a%d)&&!(b%d); }

int main()
{
	freopen("2299.in","r",stdin);
	freopen("2299.out","w",stdout);
	long long T; scanf("%lld",&T);
	while (T--)
	{
		long long a,b,x,y; scanf("%lld %lld %lld %lld",&a,&b,&x,&y);
		if (!a && !b)
		{
			if (!x && !y) printf("Y\n");
			else printf("N\n");
		}
		else
		{
			d = gcd(a,b)<<1;
			if (okay(x,y)||okay(x-a,y-b)||okay(x-b,y-a)||okay(x-a-b,y-a-b)) printf("Y\n");
			else printf("N\n");
		}
	}
	fclose(stdin); fclose(stdout);
	return 0;
}
posted @ 2015-04-09 07:55  lmxyy  阅读(127)  评论(0编辑  收藏  举报