Evanyou Blog 彩带

P2520 [HAOI2011]向量

题目描述

给你一对数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)

接下来t行每行四个整数a,b,x,y (-2*10^9<=a,b,x,y<=2*10^9)

 

输出格式:

 

t行每行为Y或者为N,分别表示可以拼出来,不能拼出来

 

输入输出样例

输入样例#1: 
  1. 3
  2. 2 1 3 3
  3. 1 1 0 1
  4. 1 0 -2 3
输出样例#1: 
  1. Y
  2. N
  3. Y

说明

样例解释:

第一组:(2,1)+(1,2)=(3,3)

第三组:(-1,0)+(-1,0)+(0,1)+(0,1)+(0,1)=(-2,3)

 

Solution:

  首先,我们注意到题目中的向量实际只有4种操作:(a,b),(b,a),(a,b),(b,a)

  于是由题意得方程组:

  k(a,b)+q(b,a)+w(a,b)+c(b,a)=(x,y)>(k+w)a+(q+c)b=x,(kw)b+(qc)a=y

  由裴蜀定理可得:ax+by=c

  xy有整数解的充要条件是gcd(a,b)|c

  证明:令a=pgcd(a,b),b=qgcd(a,b)

  则原式=(px+qy)gcd(a,b)=c

  显然因为gcd(a,b)为整数,而要使xy为整数,则gcd(a,b)|c

  我们回到开始的方程组(k+w)a+(q+c)b=x,(kw)b+(qc)a=y

  由裴蜀定理易得:(k+w),(q+c),(k-w),(q-c)均为整数的充要条件是gcd(a,b)|xgcd(a,b)|y

  但是注意到(k+w),(k-w)有整数解不一定k和w有整数解(q+c)和(q-c)是同理的)。此时不妨设(k+w)=f,(kw)=g

  则k=(f+g)/2,w=(fg)/2

  因为2|(f+g)2|(fg)

  显然要使kw均为整数则fg均为偶数或均为奇数((q+c)(qc)同理)。

  于是我们考虑这四种情况:

  1、当(k+w),(kw),(q+c),(qc)均为偶数时,(k+w)a+(q+c)b=x 提公因数2结合 gcd(a,b)|x>gcd(a,b)2|x 同理 gcd(a,b)2|y

  2、当(k+w),(kw)为偶数,(q+c),(qc)为奇数时,(k+w)a+(q+c)b=x先左右两边同加b,再提公因数2结合 gcd(a,b)|x>gcd(a,b)2|x+b 同理gcd(a,b)2|y+a

  3、当(k+w),(kw)为奇数,(q+c),(qc)为偶数时,(k+w)a+(q+c)b=x先左右两边同加a,再提公因数2结合gcd(a,b)|x>gcd(a,b)2|x+a 同理gcd(a,b)2|y+b

  4、当(k+w),(kw),(q+c),(qc)均为奇数时,(k+w)a+(q+c)b=x先左右两边同加a+b,再提公因数2结合gcd(a,b)|x>gcd(a,b)2|x+a+b同理 gcd(a,b)2|y+a+b

  只要满足上述的任意一种情况,则说明本题k,w,q,c有整数解,说明可行,否则说明无解。

代码:

 

复制代码
  1. #include<bits/stdc++.h>
  2. #define il inline
  3. #define ll long long
  4. #define debug printf("%d %s\n",__LINE__,__FUNCTION__)
  5. using namespace std;
  6. ll t,a,b,x,y,k;
  7. il int gi()
  8. {
  9. ll a=0;char x=getchar();bool f=0;
  10. while((x<'0'||x>'9')&&x!='-')x=getchar();
  11. if(x=='-')x=getchar(),f=1;
  12. while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
  13. return f?-a:a;
  14. }
  15. il ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
  16. il bool check(ll x,ll y){return x%k==0&&y%k==0;}
  17. int main()
  18. {
  19. t=gi();
  20. while(t--){
  21. a=gi(),b=gi(),x=gi(),y=gi();
  22. k=gcd(a,b)*2;
  23. if(check(x,y)||check(x+a,y+b)||check(x+b,y+a)||check(x+a+b,y+a+b))printf("YE5\n");
  24. else printf("N0\n");
  25. }
  26. return 0;
  27. }
复制代码

 

posted @   five20  阅读(965)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Live2D
欢迎阅读『P2520 [HAOI2011]向量』
点击右上角即可分享
微信分享提示