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

posted @ 2020-10-23 22:04  茄子Min  阅读(137)  评论(0编辑  收藏  举报