描述 Description
给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y)。 说明:这里的拼就是使得你选出的向量之和为(x,y)输入格式 Input Format
第一行数组组数t,(t<=50000)接下来t行每行四个整数a,b,x,y (-2*10^9<=a,b,x,y<=2*10^9)输出格式 Output Format
t行每行为 Y 或者为 N ,分别表示可以拼出来,不能拼出来样例输入 Sample Input
32 1 3 31 1 0 11 0 -2 3样例输出 Sample Output
YNY时间限制 Time Limitation
1s注释 Hint
样例解释: 第一组:(2,1)+(1,2)=(3,3)第三组:(-1,0)+(-1,0)+(0,1)+(0,1)+(0,1)=(-2,3)来源 Source
haoi2011思路:这个题就是一个真正的数学题哇........题目中说道你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a),看似有很多情况。其实你列下来可以得到一个方程。因为可以设(x,y)=A(a,b)+B(a,-b)+C(b,a)+D(b,-a);A,B,C,D这四个系数的式子就可以表示所有情况了//好好想一下。然后把这个式子拆成两个方程
①x=a(A+B)+b(C+D)
②y=a(C-D)+b(A+B);//去括号然后合并同类项,相信大家都会吧
然后要想使这个向量(a,b)变成(x,y)那么一定要满足这两个方程有解吧。所以先特判一下a=0或b=0这两种情况。然后求出gcd(a,b);因为要是这两个方程有解那么就一定要满足x%(gcd(a,b))==0和y%(gcd(a,b))==0这两个情况。然后你保证了方程①和②有解的情况下你并不能保证①+②有解。所以①加②就可以化为
③x+y=a(A+B)+b(C+D)+a(C-D)+b(A-B);
x+y=A(a+b)+B(a-b)+C(a+b)+D(b-a)
x+y=(A+C)*(a+b)+(B-D)*(a-b)
//这应该也是很好理解的吧
然后你只需保证这个方程有解即可,及为(x+y)%(a+b)==0&&(x+y)%(a-b)==0。那么这个向量(a,b),就可以变成(x,y);
代码如下:
1 #include2 #include 3 #include 4 #include 5 #include 6 #define ll long long 7 using namespace std; 8 inline ll read() 9 {10 char ch=getchar();11 ll x=0,f=1;12 while(ch>'9'||ch<'0')13 {14 if(ch=='-')15 f=-1;16 ch=getchar();17 }18 while(ch>='0'&&ch<='9')19 {20 x=x*10+ch-'0';21 ch=getchar();22 }23 return x*f;24 }25 ll gcd(ll a,ll b)26 { return b==0?a:gcd(b,a%b);}27 int main()28 {29 int t=read();30 for(int i=1;i<=t;i++)31 {32 ll a=read(),b=read(),x=read(),y=read();33 a=abs(a);b=abs(b);34 if(!a)35 {36 if(x%b==0&&y%b==0)37 cout<<'Y'<