【BZOJ2299】[HAOI2011]向量(数论)

【BZOJ2299】[HAOI2011]向量(数论)

题面

BZOJ
洛谷

题解

首先如果我们的向量的系数假装可以是负数,那么不难发现真正有用的向量只有\(4\)个,我们把它列出来。\((a,b)(a,-b)(b,a)(b,-a)\),我们假设这四个出现的次数分别为\(c1,c2,c3,c4\)
那么我们就有方程。

\[\begin{cases}a(c1+c2)+b(c3+c4)&=x\\b(c1-c2)+a(c3-c4)&=y\end{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;
}
posted @ 2018-11-05 20:37  小蒟蒻yyb  阅读(237)  评论(0编辑  收藏  举报