CF982E(很神奇的exgcd)

n*m的球桌的(x,y)点上有一个球,给球任意八个方向的初速度问球能否进洞,并把洞口坐标输出

主要是很难想到补边,以及用exgcd求出的交点坐标不一定是第一个交点,甚至有可能是另一个方向的交点,这个有点难处理

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
typedef __int64 ll;
int n, m, x, y, vx, vy;
ll ans_x, ans_y;

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

int solve() {
    if (vx*vy == 0) {
        if (vx == 0) {
            if (x == 0 || x == n) {
                if (vy == 1) {ans_x = x; ans_y = m;}
                else {ans_x = x; ans_y = 0;}
                return true;
            }
            else return false;
        }
        if (vy == 0) {
            if (y == 0 || y == m) {
                if (vx == 1) {ans_x = n; ans_y = y;}
                else {ans_x = 0; ans_y = y;}
                return true;
            }
            else return false;
        }
    }
    ll k = vx*vy; ll c = y - k*x;
    ll X, Y;
    ll d = exgcd(m, -k*n, X, Y);

    if (c % d) return false;
    ll tmpx = c / d * X;
    ll r = -k*n / d;
    r = r < 0 ? -r : r;

    tmpx = (tmpx % r + r) % r;
    if (vy > 0 && tmpx == 0) tmpx = r;

    if (vy < 0 && tmpx > 0) {
        tmpx = (tmpx - (tmpx/r+1)*r) % r;
    }

    ll tmpy = (c - m*tmpx) / n;

    if (tmpx % 2 != 0) ans_y = m;
    else ans_y = 0;
    if (tmpy % 2 != 0) ans_x = n;
    else ans_x = 0;
    return true;

}

int main() {
    scanf("%d%d%d%d%d%d",&n,&m,&x,&y,&vx,&vy);
    if (!solve()) puts("-1");
    else printf("%I64d %I64d\n", ans_x, ans_y);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值