[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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章