[HDU - 5114 ] Collision (不定方程,exgcd,分类讨论)
[HDU - 5114 ] Collision (不定方程,exgcd,分类讨论)
题目链接:HDU - 5114
题面:
题意:
每一组测试给你六个整数:\(x,y,x1,y1,x2,y2\),代表在一个长为\(\mathit x\), 高为\(\mathit y\) 的矩形网格中,
最初由两个小球,分别在\((x1,y1),(x2,y2)\),小球在二维平面上的速度为\((1,1)\),现在问两个小球第一次相遇是在哪个位置?
思路:
因为小球在二维平面上的速度为\((1,1)\),所以小球相遇的位置一定是整数格子或整数格点的中间位置。
于是我们可以让平面拉伸2倍,这样使其计算过程中全是整数,输出时除以2即可。
分以下4类情况进行讨论:
1、两点重合,则最初时就相遇。
2、\(x1=x2\),那么两球的横坐标始终相等,设\(tm\)秒后相遇,则\(tm\) 是让两球纵坐标第一次相等的时间 。
3、\(x1=x2\),同上,那么两球的纵坐标始终相等,设\(tm\)秒后相遇,则\(tm\) 是让两球横坐标第一次相等的时间 。
单独计算两球横坐标和纵坐标第一次相等的时间方法:
拿横坐标举例:
若\(x1=x2\),那么初始就相等,
否则:
假设:\(x1>x2\),那么在第一个小球第一次到达右壁反弹前,二球横坐标不可能相等,
当小球1第一次到达右壁时,二者的距离差距是\(x1-x2\),相对速度为2,则相等需要用时:
\(time_x=x-x1+(x1-x2)/2=x-x1+x1/2-x2/2=x-x1/2-x2/2=x-(x1+x2)/2\).
同理可得纵坐标第一次相等需要用时:\(time_y=y - (y1 + y2) / 2\)。
4、\(x1\not=x2,y1\not=y2\)时:
二者的横纵坐标第一次相等时,对应方向(单独考虑 x方向和 y方向)上的是相背而驰的,则相对的速度是2,而横/纵坐标的周期长度是\(2*x,2*y\),则横纵坐标相等的周期分别为\(x,y\)。
那么可以建立如下不定方程:
\(k_1\times x +time_x=k_2\times y +time_y\)
一般式为:
\(k_1\times x+k_2\times y=time_y-time_x\)(k1,k2为待定系数,所以正负号无关紧要。)
那么我们可以用exgcd算法来判断方程是否有解,以及最小正整数解。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bits/stdc++.h>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
// ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
// ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;}
void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '\n' : ' ');}}
void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '\n' : ' ');}}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
ll x, y, x1, y1, x2, y2;
ll move_(ll now, ll step, ll bond)
{
now += step;
now %= (bond * 2);
if (now > bond) {
now = bond - (now - bond);
}
return now;
}
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
void exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b) {x = 1, y = 0; return;}
exgcd(b, a % b, y, x); y -= a / b * x;
return;
}
ll Exgcd(ll A, ll B, ll C)
{
// Ax+By=c
// return minimum x1 make equation is satisfied
ll k1, k2, g = gcd(A, B);
if (C % g) { return -1; }
A /= g, B /= g, C /= g;
exgcd(A, B, k1, k2);
return (k1 * C % B + B) % B;
}
int main()
{
#if DEBUG_Switch
freopen("D:\\code\\input.txt", "r", stdin);
#endif
//freopen("D:\\code\\output.txt","w",stdout);
int t;
t = readint();
for (int icase = 1; icase <= t; icase++) {
printf("Case #%d:\n", icase );
x = readint(); y = readint();
x1 = readint(); y1 = readint();
x2 = readint(); y2 = readint();
x *= 2; y *= 2; x1 *= 2; y1 *= 2; x2 *= 2; y2 *= 2;
ll time_x = x - (x1 + x2) / 2;
ll time_y = y - (y1 + y2) / 2;
if (x1 == x2 && y1 == y2) {
printf("%.1f %.1f\n", 0.5 * x1, 0.5 * y1);
} else if (x1 == x2) {
ll ans_x = move_(x1, time_y, x);
ll ans_y = move_(y1, time_y, y);
printf("%.1f %.1f\n", 0.5 * ans_x, 0.5 * ans_y);
} else if (y1 == y2) {
ll ans_x = move_(x1, time_x, x);
ll ans_y = move_(y1, time_x, y);
printf("%.1f %.1f\n", 0.5 * ans_x, 0.5 * ans_y);
} else {
ll k1 = Exgcd(x, y, time_y - time_x);
if (k1 == -1) {
printf("Collision will not happen.\n");
} else {
ll ans_x = move_(x1, time_x + k1 * x, x);
ll ans_y = move_(y1, time_x + k1 * x, y);
printf("%.1f %.1f\n", 0.5 * ans_x, 0.5 * ans_y);
}
}
}
return 0;
}