Codeforces 982E - 扩展欧几里得

匿名 (未验证) 提交于 2019-12-03 00:22:01

解题思路:

考虑当质点移动轨迹的直线斜率为1的时候,有轨迹方程 y = x + c,显然把原先起点x1,y1代入就可以求出c的值.

将质点的反弹等价于直线轨迹(由对称性质可得)。由x - y = -c得,要使得质点可以从顶角出去就等价于质点的直线轨迹会经过一点

(a*n,b*m),代入方程得a*n - b*m = -c,要使方程有解gcd(n,m) | c, c = k*gcd(n,m),根据扩展欧几里得就可以求出方程得一个解。初始化 x = k就可以得到c的一个解,等价于gcd(n,m)*k,因为k是可以提取的所以没有影响.另t*n%m==0,那么最小正整数t就是m/gcd(n,m),所以最小的a肯定是在t之内所以a要对t求余求最小的那个坐标.

至于其他方向向量不是(1,1)的可以用过对称转化为向量(1,1)去求解.

矩形平铺在坐标轴的坐标位置有明显的规律可循,画图就可以直接看出来了.


#include<bits/stdc++.h> using namespace std; typedef long long ll; ll x,y,c; void ex_euclid(ll a,ll b)   {       if(!b){           x = c;           y = 0;       }else{           ex_euclid(b,a%b);           ll tem =x;           x = y;           y = tem - a/b*y;       }   }   int main() { 	int n,m,x1,y1,vx,vy; 	scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&vx,&vy); 	if(!vx&&!vy) return 0*puts("-1"); 	if(vx&&!vy){ 		if(y1==0){ 			if(vx==-1) printf("0 0\n"); 			else printf("%d 0\n",n); 		}else if(y1==m){ 			if(vx==-1) printf("0 %d\n",m); 			else printf("%d %d\n",n,m);			 		}else puts("-1"); 		return 0; 	}if(!vx&&vy){ 		if(x1==0){ 			if(vy==-1) printf("0 0\n"); 			else printf("0 %d\n",m); 		}else if(x1==n){ 			if(vy==-1) printf("%d 0\n",n); 			else printf("%d %d\n",n,m);			 		}else puts("-1"); 		return 0; 	}  	int fx = 0,fy = 0; 	if(vx==-1) fx = 1,x1 = n - x1; 	if(vy==-1) fy = 1,y1 = m - y1; 	int g = __gcd(n,m),_m = m/g; 	c = (x1-y1)/g; 	if((x1-y1)%g!=0) return 0*puts("-1"); 	ex_euclid(n,m); 	x = (x%_m + _m - 1)%_m + 1,y = -((x1-y1)-x*n)/m;//x为0时应该是_m  	int ansn = n,ansm = m; 	if(x%2==0) ansn = n - ansn; 	if(y%2==0) ansm = m - ansm; 	if(fx) ansn = n - ansn;//对称取反(坐标上的规律)  	if(fy) ansm = m - ansm; 	printf("%d %d\n",ansn,ansm); 	return 0; }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!