您的位置:首页 > 其它

[BZOJ2299]-[HAOI2011]向量-裴蜀定理

2018-03-03 18:56 369 查看

说在前面

并没有什么想说的,但是要保持格式=w=

题目

BZOJ2299传送门

题面

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

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

输入输出格式

输入格式:

第一行一个整数T,表示数据组数(T≤50000)

接下来每行一组数据,包含四个整数a,b,x,y

输出格式:

对于每组数据,输出一行:

如果可以输出Y,不行则输出N

解法1

如果只用前四个向量,那么只能凑出来(u1 a,u2 b)(u1 a,u2 b)这样的向量;如果只用后四个,也只能(v1 b,v2 a)(v1 b,v2 a)这样的向量。因此,前四个向量和后四个向量 是独立的,它们互不干扰

那么假设前四个的贡献是(u1 a,u2 b)(u1 a,u2 b),后四个的贡献是(v1 b,v2 a)(v1 b,v2 a),那么可以列出方程:{u1a+v1b=xu2b+v2a=y{u1a+v1b=xu2b+v2a=y,其中要求u1,u2u1,u2奇偶一致,v1,v2v1,v2奇偶一致(因为单组内a和b的个数差始终是2的倍数)

那么枚举u和v的奇偶性即可,然后用x和y减去奇数多出来的那一个,那么如果有一组偶数解u,v,那么此题有解。

不妨把x和y都除以二,那么这样限制就没有了,直接用裴蜀定理判定即可。(裴蜀:ax+by=c有解当且仅gcd(a,b)|c)

解法2

可以发现,原来的八种向量,其实可以等价于以下几种操作:

对x或y,加上或减去2*a

对x或y,加上或减去2*b

x+a,y+b

x+b,y+a

而且第3,4种操作,最多用一次。(超过两次的部分可以替换成1或2操作)

于是枚举用没有用3,4操作,如果用了就减掉,之后也是裴蜀定理判断

下面是代码

两种方法其实是差不多的,代码也毫无区别

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int T ;
long long a , b , x , y , d ;

long long gcd( long long a , long long b ){
return !b ? a : gcd( b , a%b ) ;
}
bool check( long long x , long long y ){
if( x&1 || y&1 ) return false ;
return ( x>>1 )%d == 0 && ( y>>1 )%d == 0 ;
}
int main(){
scanf( "%d" , &T ) ;
while( T -- ){
scanf( "%lld%lld%lld%lld" , &a , &b , &x , &y ) ;
d = gcd( a , b ) ;
if( check( x-a, y-b ) || check( x-b , y-a ) || check( x , y ) || check( x-a-b , y-a-b ) )
puts( "Y" ) ;
else puts( "N" ) ;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: