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\)同理,现在考虑如何保证奇偶性相同呢?不妨分类讨论:
- \(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\)
- \(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)\)
- \(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)\)
- \(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";
}
}