[haoi2011]向量

给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y)。
说明:这里的拼就是使得你选出的向量之和为(x,y)

 

 

题解:

首先这八个向量是不必都用上的,去除那些加负号后等同的向量后剩下了四个(a,b)(a,-b)(b,a)(b,-a)。

最后要组成的向量是(x,y),由向量运算法则设这样的式子:

(x,y)=A(a,b)+B(a,-b)+C(b,a)+D(b,-a);

可化成:

x=a(A+B)+b(C+D)

y=b(A-B)+a(C-D)

设x1=A+B,y1=C+D,x2=A-B,y2=C-D;

x=ax1+by1;

y=bx2+ay2;

然后我们就可以看出来了,如果A,B,C,D有解,

那么x1+x2,y1+y2都是偶数;

然后利用拓展gcd求出一组x1,y1,x2,y2,

判断一下即可;

细节上主要注意直接求出的一组解可能不符条件,但变形后就符合条件了

由于判断的是奇偶,每个方程的解最多两种情况,乘起来一共四种情况,都需要判断;

详见代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define FILE "dealing"
#define LL long long 
#define up(i,j,n) for(int i=j;i<=n;i++)
#define pii pair<LL,LL>
#define piii pair<LL,pair<LL,LL> >
template<typename T> inline bool chkmin(T &a,T b){return a>b?a=b,true:false;}
template<typename T> inline bool chkmax(T &a,T b){return a<b?a=b,true:false;}
namespace IO{
    char *fs,*ft,buf[1<<15];
    inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    inline int read(){
        LL x=0;int ch=gc();bool f=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
        while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
        return f?-x:x;
    }
}using namespace IO;
LL a,b,x,y,t;
namespace OI{
    void gcd(LL a,LL b,LL& d,LL &x,LL &y){
        if(!b){d=a,x=1,y=0;return;}
        gcd(b,a%b,d,x,y);
        LL t=x;
        x=y;
        y=t-a/b*x;
    }
    char check(){
        LL d,x1,y1,x2,y2;
        gcd(a,b,d,x1,y1);
        x2=y1,y2=x1;
        a/=d,b/=d;
        if(x%d||y%d)return 'N';
        x1*=x/d,y1*=x/d,x2*=y/d,y2*=y/d;
        if(!((x1+x2)&1)&&!((y1+y2)&1))return 'Y';
        x1+=b,y1-=a;
        if(!((x1+x2)&1)&&!((y1+y2)&1))return 'Y';
        x2+=a,y2-=b;
        if(!((x1+x2)&1)&&!((y1+y2)&1))return 'Y';
        x1+=b,y1-=a;
        if(!((x1+x2)&1)&&!((y1+y2)&1))return 'Y';
        return 'N';
    }
    void slove(){
        t=read();
        while(t--){
            a=read(),b=read(),x=read(),y=read();
            printf("%c\n",check());
        }
    }
}
int main(){
    freopen(FILE".in","r",stdin);
    freopen(FILE".out","w",stdout);
    using namespace OI;
    slove();
    return 0;
}

 

posted @ 2016-10-27 21:23  CHADLZX  阅读(363)  评论(0编辑  收藏  举报