【BZOJ2299】[HAOI2011]向量(数论)
题面
题解
首先如果我们的向量的系数假装可以是负数,那么不难发现真正有用的向量只有(4)个,我们把它列出来。((a,b)(a,-b)(b,a)(b,-a)),我们假设这四个出现的次数分别为(c1,c2,c3,c4)。
那么我们就有方程。
[egin{cases}a(c1+c2)+b(c3+c4)&=x\b(c1-c2)+a(c3-c4)&=yend{cases}
]
因为合法的情况一定保证了所有数都是整数,因此(c1+c2)和(c1-c2)要同奇偶,(c3,c4)同理。
首先先判断是否有整数解,那么拿(d=gcd(a,b))直接检查(d|x,d|y)就行了。
有了整数解我们很容易写出通解,因为只需要考虑奇偶性,所以根本不需要求出一组合法解,只需要求出一种合法的奇偶性。剩下的只需要(check)一下最终能否做到配对的奇偶性即可。
那么讨论(a,b)的奇偶性和(x,y)的奇偶性。(都是除掉(gcd)之后的值)
当(a,b)都为奇数的时候,显然只有(x,y)同奇偶的时候才有解,否则无法做到对应系数奇偶性相等。
当(a,b)一奇一偶的时候,发现偶数对应的系数可以随意调整,因此一定有解。
当(a,b)都是偶数的时候,听说你把(gcd)除掉之后还能两个数都是偶数??
那就做完了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int main()
{
int T=read();
while(T--)
{
int a=read(),b=read(),x=read(),y=read();
int d=__gcd(a,b);
if(x%d||y%d){puts("N");continue;}
a/=d;b/=d;x/=d;y/=d;
bool fl=false;
if((a&1)&&(b&1)&&((x&1)==(y&1)))fl=true;
if(((a&1)&&!(b&1))||(!(a&1)&&(b&1)))fl=true;
puts(fl?"Y":"N");
}
return 0;
}