【HAOI2011】 向量
数论好劲啊
原题:
给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y)。
说明:这里的拼就是使得你选出的向量之和为(x,y)
t<=50000,-2*10^9<=a,b,x,y<=2*10^9
这题我自己想出了思路,但是怎么都WA,最后膜拜lzx的题解才A
首先其实向量只有四个,比如(a,b)和(-a,-b)是一个东西
然后就可以列出酱紫的方程:
a(x1+x2)+b(y1+y2)=x
b(x1-x2)+b(y1-y2)=y
如果想要有解,首先要保证两个方程分别有解,这个根据扩展欧几里得的性质判断(c%gcd(a,b)!=0时ax+by=c有解)
然后还要满足解出来的(x1+x2),(y1+y2),(x1-x2),(y1-y2)能够解出整数解x1,x2,y1,y2
设x1+x2=e,x1-x2=f,e+f=2*x1,所以当e+f为偶数时有解,y同理
exgcd搞一下判断即可
然后有个问题就是exgcd解出来的答案可能满足条件,但是对这个答案进行一些调整依旧满足条件但是奇偶性变了
调整最多就是x或y加减a或b,总共四种情况,都不能满足偶数条件的时候就无解了
注意longlong
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 using namespace std; 8 #define ll long long 9 ll rd(){int z=0,mk=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 12 return z*mk; 13 } 14 ll gcd(ll x,ll y){ return y?gcd(y,x%y):x;} 15 void exgcd(ll a,ll b,ll &x,ll &y){ 16 if(!b){ x=1,y=0; return ;} 17 exgcd(b,a%b,x,y); 18 ll c=x; x=y,y=c-a/b*x; 19 } 20 int n; 21 char chck(ll x1,ll y1,ll x2,ll y2,ll a,ll b){ 22 if(!((x1+x2)&1) && !((y1+y2)&1)) return 'Y'; 23 x1+=b,y1-=a; 24 if(!((x1+x2)&1) && !((y1+y2)&1)) return 'Y'; 25 x2+=a,y2-=b; 26 if(!((x1+x2)&1) && !((y1+y2)&1)) return 'Y'; 27 x1+=b,y1-=a; 28 if(!((x1+x2)&1) && !((y1+y2)&1)) return 'Y'; 29 return 'N'; 30 } 31 int main(){//freopen("ddd.in","r",stdin); 32 cin>>n; 33 ll a,b,x,y; 34 ll x1,x2,y1,y2,ggcd; 35 while(n--){ 36 a=rd(),b=rd(),x=rd(),y=rd(); 37 exgcd(a,b,x1,y1),exgcd(a,b,y2,x2); 38 ggcd=gcd(a,b); 39 if(x%ggcd || y%ggcd) printf("N\n"); 40 else printf("%c\n",chck(x1*x/ggcd,y1*x/ggcd,x2*y/ggcd,y2*y/ggcd,a/ggcd,b/ggcd)); 41 //if(((x1*x+x2*y)/ggcd)&1 || ((y1*x+y2*y)/ggcd)&1) printf("N\n"); 42 //else printf("Y\n"); 43 } 44 return 0; 45 }