P2520向量—裴蜀定理应用

P2520向量—裴蜀定理应用

题目:
给你一对数\(a,b\),你可以任意使用\((a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)\)这些向量,问你能不能拼出另一个向量\((x,y)\)

说明:这里的拼就是使得你选出的向量之和为\((x,y)\)

首先,减去\((a,b)\)等价于加上\((-a,-b)\),其余同理,所以只需要考虑四个向量:\((a,b),(b,a),(-a,b),(-b,a)\)

所以可以得到方程组:

\[\left\{ \begin{aligned} (A-C)a+(B-D)b&=x \\ (B+D)a+(A+C)b&=y \\ \end{aligned} \right. \]

\(\gcd(a,b)=d\),则两个方程有解的充要条件是\(d|x,d|y\)(裴蜀定理)。此时即得到了\(A-C,A+C,B-D,B+D\)的值,不妨记为\(f_1,f_2,f_3,f_4\)。则:\(A=\frac{f_1+f_2}{2},C=\frac{f_2-f_1}{2},B=\frac{f_3+f_4}{2},D=\frac{f_4-f_3}{2}\)

所以说,\(f_1,f_2\)需要奇偶性相同,\(f_3,f_4\)同理,现在考虑如何保证奇偶性相同呢?不妨分类讨论:

  1. \(f_1,f_2,f_3,f_4\)均为偶数,此时有:\(x=f_1a+f_3b\),提取一个公约数\(2\),变成:\(d|\frac{x}{2}\implies 2d|x\),同理可以得到:\(2d|y\)

\(2d|x,2d|y\)

  1. \(f_1,f_2,f_3,f_4\)均为奇数,此时有:\(x+a+b=(f_1+1)a+(f_3+1)b\),再提取一个公约数\(2\),变成\(2d|(x+a+b),2d|(y+a+b)\)

\(2d|(x+a+b),2d|(y+a+b)\)

  1. \(f_1,f_2\)为偶数,\(f_3,f_4\)为奇数,此时有:\(x+b=f_1a+(f_3+1)b,y+a=(f_4+1)a+f_2b\),类似的我们可以得到:\(2d|(x+b),2d|(y+a)\)

\(2d|(x+b),2d|(y+a)\)

  1. \(f_1,f_2\)为奇数,\(f_3,f_4\)为偶数,此时有:\(x+a=(f_1+1)a+f_3b,y+b=f_4a+(f_2+1)b\),类似的我们可以得到:\(2d|(x+a),2d|(y+b)\)

\(2d|(x+a),2d|(y+b)\)

四种情况满足一种即可,前提是\(d|x,d|y\)

#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}
bool check(int d,int a){
	return a%d==0;
}
signed main(){
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		int a,b,x,y,d1,d2;
		cin>>a>>b>>x>>y;
		d1=gcd(a,b);
		if(x%d1==0&&y%d1==0){
			d1<<=1;
			if(check(d1,x+a+b)&&check(d1,y+a+b))cout<<"Y";
			else if(check(d1,x)&&check(d1,y))cout<<"Y";
			else if(check(d1,x+a)&&check(d1,y+b))cout<<"Y";
			else if(check(d1,x+b)&&check(d1,y+a))cout<<"Y";
			else cout<<"N";
		}
		else cout<<"N";
		cout<<"\n";
	}
}
posted @ 2022-12-20 22:05  spdarkle  阅读(41)  评论(0编辑  收藏  举报