[BZOJ2299] [HAOI2011]向量

[HAOI2011]向量

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*10^9<=a,b,x,y<=2*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)

Solution:
首先8种向量只有四个本质不同的向量。
我们设有 k1(a,b),k2(a,b),k3(b,a),k4(b,a)
那么我们有 a(k1+k2)+b(k3+k4)=x a(k3k4)+b(k1k2)=y ,我们记 p1=k1+k2,p2=k3+k4,p3=k3k4,p4=k1k2 ,那么 k1,k2,k3,k4 有整数解的条件是 p1p4(mod2)p2p3(mod2) ,我们用拓展欧几里得接出 p1,p2,p3,p4 的一组解,显然 mod2 将每一个不定方程分为两类,一共四种情况,一一判断即可

Code :

/************************************************************************* > File Name: bzoj2299.cpp > Author: Archer ************************************************************************/
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

inline ll read(){
    ll x = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10ll + ch - '0'; ch = getchar(); }
    return f == 1 ? x : -x;
}
inline void exgcd(ll a, ll &x, ll b, ll &y){
    if (b == 0) {x = 1ll; y = 0ll; return;}
    ll x1, y1; exgcd(b, x1, a % b, y1);
    x = y1; y = x1 - a / b * y1; 
}
inline ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
inline bool check(ll p1, ll p2, ll p3, ll p4){
    return (((p1-p4)%2 == 0) && ((p2-p3)%2 == 0));
}
int main(){
    for (ll T = read(); T--;){
        ll a = read(), b = read(), x = read(), y = read();
        if (a < b) swap(a, b);
        if (a == 0) {puts(x == 0 && y == 0 ? "Y" : "N"); continue;}

        ll d = gcd(a, b); ll p1, p2, p3, p4, d1 = b / d, d2 = a / d;
        if (x % d != 0 || y % d != 0) {puts("N"); continue;}
        ll t1, t2; exgcd(a / d, t1, b / d, t2); 
        p1 = t1 * x / d; p2 = t2 * x / d; 
        p3 = t1 * y / d; p4 = t2 * y / d;
        if (check(p1, p2, p3, p4) || check(p1 + d1, p2 - d2, p3, p4)
          ||check(p1, p2, p3 + d1, p4 - d2) || check(p1 + d1, p2 - d2, p3 + d1, p4 - d2)) puts("Y");
        else puts("N");
    }
    return 0;
}

你可能感兴趣的:([BZOJ2299] [HAOI2011]向量)