HDU 5114 Collision(一元线性同余方程)

201 篇文章 10 订阅

Description
两个质点在一个x*y的矩形区域内,初始位置(x1,y1)和(x2,y2)给出,两个质点保持(1,1)的速度运动,遇到区域边界会反弹(满足反射定律),问两个质点第一次相遇的位置,如果不会相遇则输出Collision will not happen.
Input
第一行为一整数T表示用例组数,每组用例第一行为两个整数x和y表示区域规格,第二行四个整数x1,y1,x2,y2分别表示两个质点的初始位置
Output
如果两个质点会相遇则输出第一次相遇的位置,否则输出Collision will not happen.
Sample Input
3
10 10
1 1 9 9
10 10
0 5 5 10
10 10
1 0 1 10
Sample Output
Case #1:
6.0 6.0
Case #2:
Collision will not happen.
Case #3:
6.0 5.0
Solution
两个质点如果相遇那么一定在整点或者半点处,所以首先将所有数据乘2避免小数出现,设第一次两点横坐标相同的时刻为tx,若x1=x2则任意时刻两质点横坐标相同,若x1!=x2,那么有(x1+tx)%x=(x2+tx)%x且((x1+tx)/x)%2!=((x2+tx)/x)%2(横坐标不同时两点相遇前碰撞次数一定不同),由上式可以很快求出tx=(2*x-(x1+x2))/2,那么两质点横坐标相同的时刻就是tx+k*x,同理可以求出ty表示第一次两质点纵坐标相同的时刻,那么第一次两质点相遇的时刻T=tx+k1*x=ty+k2*y,即k1*x=ty-tx(mod y),问题转化为求该一元线性同余方程的解
Code

#include<cstdio>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
ll x1,y1,x2,y2,x,y;
ll extend_gcd(ll a,ll b,ll &x,ll &y)
{ 
    ll d=a;
    if(b!=0)
    {
        d=extend_gcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else 
    {
        x=1;
        y=0;
    }
    return d;
}
ll linear(ll a,ll b,ll c)//求解一元线性同余方程ax=b(mod c)
{
    ll x,y;
    ll g=extend_gcd(a,c,x,y);
    if(b%g)//无解 
        return -1;
    x=x*(b/g);
    ll mod=c/g;
    x=(x%mod+mod)%mod;
    return x;
}
ll solve()
{
    ll fx,fy,tx,ty;
    fx=(x1==x2),fy=(y1==y2);
    tx=(2*x-(x1+x2))/2,ty=(2*y-(y1+y2))/2;
    if(fx&&fy)return 0;
    if(fx)return ty;
    if(fy)return tx;
    ll ans=linear(x,ty-tx,y);
    if(ans==-1)return INF;
    return tx+ans*x;
}
int main()
{
    int T,res=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&x1,&y1,&x2,&y2);
        x*=2,y*=2,x1*=2,y1*=2,x2*=2,y2*=2;
        ll t=solve();
        printf("Case #%d:\n",res++);
        if(t==INF)printf("Collision will not happen.\n");
        else
        {
            ll xx=t+x1,yy=t+y1;
            if((xx/x)%2==0)xx%=x;
            else xx=((x-xx)%x+x)%x;
            if((yy/y)%2==0)yy%=y;
            else yy=((y-yy)%y+y)%y;
            printf("%.1lf %.1lf\n",xx/2.0,yy/2.0);
        }
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值