1. 程式人生 > >HDU 5114 2014ICPC北京現場賽 C - Collision (擴充套件歐幾里得)

HDU 5114 2014ICPC北京現場賽 C - Collision (擴充套件歐幾里得)

題目連結

在n*m的方格的兩個整數點處發射初速度都為(1, 1)的質點,質點在邊界會發生彈性碰撞,問兩質點能否相遇。若能,求出二者第一次相遇的座標。

首先為了避免小數的出現,將座標全部擴大為原來的兩倍。

這種碰撞問題顯然需要將速度正交分解,然後有四種情況:

(1)x1==x2&y1==y2 此時顯然t=0。

(2)x1==x2&&y1 != y2 此時顯然結果取決於不相等的y,經過推導可以得出相遇的t = m - (y1+y2)/2。

(3)x1 != x2&&y1==y2 同上,t = n - (x1+x2)/2。

(4)x1 != x2 && y1 != y2 這個時候不能在一個週期裡相遇,根據(2)(3)的結果,此時就應該是:

m - (y1 + y2)/2 + x*m = n - (x1 + x2)/2 * y*n

對於這個一元線性同餘方程,可以用擴充套件歐幾里得得到它的解,需要注意的是這裡需要的是它的最小非負整數解。

顯然無解的情況就是( (m - (y1+y2)/2) - (n - (x1+x2)/2) % gcd(n, m) != 0)。

最後用求出的時間算出在座標範圍內的最終座標然後恢復到二分之一即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
typedef long long ll;
using namespace std;

const int maxn = 200050;

int t;
ll n, m, xa, xb, ya, yb;

ll ex_gcd(ll a,ll b, ll &x, ll &y)
{
    if(b == 0) {x = 1, y = 0; return a;}
    ll d = ex_gcd(b, a%b, y, x);
    y -= a/b*x;
    return d;
}

int main()
{
    scanf("%d", &t);
    int kase = 0;
    while(t--)
    {
        scanf("%lld%lld", &n, &m);
        scanf("%lld%lld%lld%lld", &xa, &ya, &xb, &yb);
        printf("Case #%d:\n", ++kase);
        xa <<= 1, xb <<= 1, ya <<= 1, yb <<= 1, n <<= 1, m <<= 1;
        ll ans = -1, ta = n - (xa+xb)/2, tb = m - (ya+yb)/2;
        if(xa == xb && ya == yb) ans = 0;
        if(ya == yb && xa != xb) ans = ta;
        if(xa == xb && ya != yb) ans = tb;
        if(xa != xb && ya != yb)
        {
            ll x, y;
            ll d = ex_gcd(n, m, x, y);
            ll tmp = tb - ta;
            if(tmp % d != 0) ans = -1;
            else
            {
                x *= (tmp/d);
                x =(x%(m/d) + (m/d)) % (m/d);
                ans = ta + n*x;
            }
        }
        if(ans == -1) puts("Collision will not happen.");
        else
        {
            xa = (xa + ans) % (n*2);
            ya = (ya + ans) % (m*2);
            if(xa > n) xa = 2*n - xa;
            if(ya > m) ya = 2*m - ya;
            printf("%.1lf %.1lf\n", xa/2.0, ya/2.0);
        }
    }
    return 0;
}