Codeforces Round #484 (Div. 2) E. Billiard

首先容易想到暴力枚举,,,
代码:

#include<bits/stdc++.h>
#define PI acos(-1)
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
#define id(x) (x == 'A' ? 0 : x == 'G' ? 1 : x == 'C' ? 2 : 3) 
using namespace std;
typedef long long ll;

template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c  = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 2e5+50;
int n,m,x,y,vx,vy;
map<pair<int,int >,int> mp; 

int main()
{
    read(n),read(m);
    read(x),read(y);
    read(vx),read(vy);

    if(vx == 0)
    {
        if(x != n && x != 0) return puts("-1");

        if(vy == 1) printf("%d %d\n",x,m);
        else printf("%d %d\n",x,0);
        return 0;
    }

    if(vy == 0)
    {
        if(y != m && y != 0) return puts("-1");

        if(vx == 1) printf("%d %d\n",n,y);
        else printf("%d %d\n",0,y);
        return 0;
    }

    while(true)
    {
        #define mk make_pair
        if((!x || x == n) && (!y || y == m)) break;
        if(mp[mk(x,y)] == 2) return puts("-1"); 
        ++ mp[mk(x,y)];

        if(vx == 1 && vy == 1)
        {
            int i = n - x , j = m - y;

            if(i > j)
            {
                x += j;
                y = m;
                vy = -1;
            }else
            {
                y += i;
                x = n;
                vx = -1;
            }

            continue;
        }

        if(vx == 1 && vy == -1)
        {
            int i = n - x , j = y;

            if(i > j)
            {
                x += j;
                y = 0;
                vy = 1;
            }else
            {
                y -= i;
                x = n;
                vx = -1;
            }

            continue;
        }

        if(vx == -1 && vy == 1)
        {
            int i = x , j = m - y;

            if(i > j)
            {
                x -= j;
                y = m;
                vy = -1;
            }else
            {
                y += i;
                x = 0;
                vx = 1;
            }

            continue;
        }

        if(vx == -1 && vy == -1)
        {
            int i = x , j = y;

            if(i > j)
            {
                x -= j;
                y = 0;
                vy = 1;
            }else
            {
                y -= i;
                x = 0;
                vx = 1;
            }

            continue;
        }
    }

    cout << x << ' ' << y << endl;

    return 0;
}

但是肯定过不去啊。。。
随便卡。
比如
1 1000000000 1 1 1 1
首先考虑特盘掉 vx=0 v x = 0 或者 vy=0 v y = 0 的情况
然后考虑无限翻转这个平面。。。
这里写图片描述

然后考虑先直接移动到两边
考虑 vy>0 v y > 0 那么就是在图左右来回移动,同时向上移动,每次移动 n n 的距离
那么现在的问题变成了 求 tn+y0(modm)
那么这个问题显然是 exgcd e x g c d tnpm=y t ∗ n − p ∗ m = − y
反之 vy<0 v y < 0 也类似,只不过先把图像反过来而已。
c++代码如下:

#include<bits/stdc++.h>
#define PI acos(-1)
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
#define id(x) (x == 'A' ? 0 : x == 'G' ? 1 : x == 'C' ? 2 : 3) 
using namespace std;
typedef long long ll;

template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c  = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 2e5+50;
int n,m,x,y,vx,vy;

int gcd(int x,int y) { return !y ? x : gcd(y,x%y); }

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

int main()
{
    read(n),read(m);
    read(x),read(y);
    read(vx),read(vy);

    if(vx == 0)
    {
        if(x != n && x != 0) return puts("-1");

        if(vy == 1) printf("%d %d\n",x,m);
        else printf("%d %d\n",x,0);
        return 0;
    }

    if(vy == 0)
    {
        if(y != m && y != 0) return puts("-1");

        if(vx == 1) printf("%d %d\n",n,y);
        else printf("%d %d\n",0,y);
        return 0;
    }

    if(vx == 1)
    {
        int d = n - x;
        x += d; y += d*vy;
    }
    else
    {
        int d = x;
        x -= d; y += d*vy;
    }

    if(vy == 1)
    {

    int xx = n,yy = m,kk = y; y %= m;
    int d = gcd(n,m);
    if(y % d != 0)
        return puts("-1");
    n /= d; m /= d; y /= d;

    ll a,b;
    exgcd(n,m,a,b);

    a = -a;
    a = a*y%m;
    if(a < 0) a += m; 


    cout << (((x == 0) && !(a&1)) || ((x == xx) && (a&1)) ? 0 : xx) <<' ';
    cout << (((kk+a*xx)/yy)&1)*yy << endl;

    }
    else
    {

    y = m - y;
    int xx = n,yy = m,kk = y;
    y%=m;

    int d = gcd(n,m);
    if(y % d != 0)
        return puts("-1");
    n /= d; m /= d; y /= d;

    ll a,b;
    exgcd(n,m,a,b);

    a = -a;
    a = a*y%m;
    if(a < 0) a += m; 


    cout << (((x == 0) && !(a&1)) || ((x == xx) && (a&1)) ? 0 : xx) <<' ';
    cout << ((((kk+a*xx)/yy)&1)^1)*yy << endl;  

    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值