传送门:bzoj2299
2299: [HAOI2011]向量
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 1209 Solved: 547
[Submit][Status][Discuss]
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<=50000)
接下来t行每行四个整数a,b,x,y (-2*109<=a,b,x,y<=2*109)
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),(2a,0)或(0,2a),(2b,0)或(0,2b),向量(a,b)和(b,a)可视为最多只需用一次,如果有两次及以上的话,可拆为别的两组的和。
于是只需判断(x,y),(x + a,y + b),(x + b,y + a),(x + a + b,y + a + b)这四种情况在(2a,0)或(0,2a),(2b,0)或(0,2b)下是否有一种情况可行了。
贴代码:
#include <iostream>
#define ll long long
using namespace std;
ll x,y,z,w;
ll k;
ll gcd(ll a,ll b){
return b == 0 ? a : gcd(b,a % b);
}
bool check(ll a,ll b){
return a % k == 0 && b % k == 0;
}
int t;
int main(){
cin >> t;
while(t --){
cin >> x >> y >> z >> w;
if (x < 0) x = 0 - x;
if (y < 0) y = 0 - y;
if (z < 0) z = 0 - z;
if (w < 0) w = 0 - w;
k = gcd(2 * x,2 * y);
if (check(z,w) || check(z + y, w + x) || check(z + x,w + y) || check(z + x + y,w + x + y))
cout << "Y" << endl;
else cout << "N" << endl;
}
return 0;
}
还有bzoj特别ge,所以交的时候把cin,cout改成scanf和printf就好
吐槽一下,HAOI简直是省选界的泥石流
本文介绍了一道HAOI2011竞赛中的向量问题,通过使用贝祖定理来解决如何利用给定的一对数构建特定向量的问题。文章详细解析了解题思路,并附带实现代码。

476

被折叠的 条评论
为什么被折叠?



