【BZOJ2299】向量(HAOI2011)-裴蜀定理

测试地址:向量
做法:本题需要用到裴蜀定理。
注意到题目中给的8个向量,实际上只有4对,每对互为相反向量,那么有:
A(a,b)+B(b,a)+C(a,b)+D(b,a)=(x,y)
这个方程当且仅当有一组A,B,C,D均为整数的解时成立。
把横纵坐标拆开,得到由下面两个方程得到的方程组:
Aa+BbCaDb=x
Ab+Ba+Cb+Da=y
尝试消去A,得到一个方程:
(b2a2)B2abC(a2+b2)D=bxay
根据裴蜀定理,该方程有一组整数解当且仅当gcd(a2b2,a2+b2,2ab)|bxay
用类似的思路消去B,C,D,和上面一个方程合起来得到4个方程,显然这4个方程组成的方程组和原方程组等价,那么新方程组有整数解的条件也就是原方程组有整数解的条件,于是我们就得到了4个条件,当且仅当这四个条件都满足时原方程组有整数解,否则就没有整数解。
(据说这题提高难度……不会做的我是不是废了T_T)
以下是本人代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
ll a,b,x,y;

ll gcd(ll a,ll b)
{
    if (a<0) a=-a;
    if (b<0) b=-b;
    return b?gcd(b,a%b):a;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
        ll d=gcd(gcd(a*a-b*b,a*a+b*b),2*a*b);
        if (abs(a*x-b*y)%d!=0) {printf("N\n");continue;}
        if (abs(b*x-a*y)%d!=0) {printf("N\n");continue;}
        if (abs(a*x+b*y)%d!=0) {printf("N\n");continue;}
        if (abs(b*x+a*y)%d!=0) {printf("N\n");continue;}
        printf("Y\n");
    }

    return 0;
}
posted @ 2018-05-17 09:32  Maxwei_wzj  阅读(107)  评论(0编辑  收藏  举报