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;
}