[HAOI2011 ]向量

  只有四个向量有意义,(a,b),(a,-b),(b,a),(b,-a)。

  很自然地列出式子。

  A(a,b) + B(a,-b) + C(b,a) + D(b,-a) = (P,Q)

  (A+B)a + (C+D)b = P

  (C -D)a + (A- B)b = Q

  上扩欧。

  x1 = A + B,y1 = C + D   

  x2 = C -  D,y2 = A  - B

  当 x1+y2 和 x2 + y1 均为偶数时,有解。

  另因为扩欧求得只是一组解,且奇偶性不同仅在相邻解。

  因此判断四组即可。

  1:原解。

  2:P式相邻解和Q式原解。

  3:P式原解和Q式相邻解。

  4:两式均相邻解。

  说明:相邻解一词由我创造,可意会。

 

// q.c
// 原来我一直学了假的exgcd...原来我一直写了错的exgcd...

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
void exgcd(LL a,LL b,LL &d,LL &x,LL &y) {
	if(!b) d=a,x=1,y=0;
	else exgcd(b,a%b,d,y,x),y-=a/b*x; // woc,y-=x*a/b就错了?目测不会溢出啊...至少对于100以内的啊...
}
bool check(int x,int y) {
	if(x%2==0&&y%2==0) return true;
	return false;
}
int main() {
	freopen("vector.in","r",stdin);
	freopen("vector.out","w",stdout);
	int T; scanf("%d",&T);
	LL a,b,x,y,d,x1,y1,x2,y2;
	while(T--) {
		scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
		exgcd(a,b,d,x1,y1);
		if(x%d||y%d) printf("N\n");
		else {
			a/=d,b/=d;
			x/=d,y/=d;
			x2=y1,y2=x1;
			x1*=x,y1*=x;
			x2*=y,y2*=y;
			if(check(x1+x2,y1+y2)) printf("Y\n");
			else if(check(x1+b+x2,y1-a+y2)) printf("Y\n");
			else if(check(x1+x2-a,y1+y2+b)) printf("Y\n");
			else if(check(x1+b+x2-a,y1-a+y2+b)) printf("Y\n");
			else printf("N\n");
		}
	}
	return 0;
}

 

posted @ 2018-04-15 14:59  qjs12  阅读(130)  评论(0)    收藏  举报