EOJ Monthly 2018.11 C 租房(几何数学)

C. 租房

单测试点时限: 1.0 秒

内存限制: 512 MB

你女朋友最近双不理你了。这一定是因为你上个月没有去和她约会。异地恋实在是太辛苦了,浦西到浦东的距离,对于你来说,就像是上海到香港的距离。

曾有诗这样写道:

世上最遥远的距离,不是生与死的距离,不是天各一方,而是我就站在你面前,你却不知道我爱你。

为了减少每次看女朋友的路程,你决定选择租房,但是你有强迫症,要求租房所在地为整点,且离女朋友家与自己家距离完全相同。如果有多处这样的房源,你想要离女朋友家距离最近的房源。

简化题意为给出两个整点(保证不同),问平面上能否找到一个整点,到这两个整点直线距离相同,且小于原来这两点之间的距离。

输入

输入四个整数 x1, y1, x2, y2 (−1018≤x1,y1,x2,y2≤1018),分别表示给定线段两点的坐标。输入保证两点不重叠。

输出

如果无解输出 NO。否则输出两个整数 x, y 表示新增的点的坐标。

如果有多解,应输出离所给点的距离尽可能小的解;如果仍然有多解,优先保证 x 最小;如果还是有多解,保证 y 尽可能小。

样例

Input

0 1 1 0

Output

0 0

Input

0 0 10 0

Output

5 0

Input

1 0 0 0

Output

NO

 

解析:

官方的题解

距离平方为奇数是不行的。证明略。

距离平方为偶数时,要么中点是一个整点(就做完了),要么 x 坐标和 y 坐标都不是整数。这时,把 (x1,y1) 到 (x2,y2) 的向量 (x,y) 除以 x,y 的 gcd,然后除以 2,旋转九十度,加到中点上,会产生两个坐标。输出小的那个就好了。

。。。我也不知道原理,几何数学上的东西...像背古诗一样...知道就是知道,不知道就是不知道

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long  ll;

const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD =2;
typedef struct node
{
    ll x;
    ll y;
}node;
ll dist;
node a1,a2;

inline ll chi(ll x,ll y)
{
    return (x%MOD+MOD)%MOD*((y%MOD+MOD)%MOD)%MOD;
}


ll cal_dist(node a,node b)
{
    return (chi((a.x-b.x),(a.x-b.x))+chi((a.y-b.y),(a.y-b.y)))%MOD;
}

ll gcd(ll x,ll y)
{
    ll tmp;
    while(y)
    {
        tmp=x%y;
        x=y;
        y=tmp;
    }
    return x;
}



int main()
{
    scanf("%lld%lld%lld%lld",&a1.x,&a1.y,&a2.x,&a2.y);

    dist=cal_dist(a1,a2);
    if(dist&1) {printf("NO\n");return 0;}
    node zho;
    zho.x=(a1.x+a2.x);
    zho.y=(a1.y+a2.y);
    if(zho.x%2==0&&zho.y%2==0)
    {
        printf("%lld %lld\n",zho.x/2,zho.y/2);
    }
    else if(zho.x%2!=0&&zho.y%2!=0)
    {
        node di;
        di.x=a1.x-a2.x;
        di.y=a1.y-a2.y;
        ll g=gcd(di.x,di.y);
        di.x/=g;
        di.y/=g;
        node ans1;
        ans1.x=(di.y+zho.x)/2;
        ans1.y=(-di.x+zho.y)/2;
        node ans2;
        ans2.x=(-di.y+zho.x)/2;
        ans2.y=(di.x+zho.y)/2;
        if(ans1.x<ans2.x||(ans1.x==ans2.x&&ans1.y<ans2.y))
        {
            printf("%lld %lld",ans1.x,ans1.y);
        }
        else
        {
            printf("%lld %lld",ans2.x,ans2.y);
        }
        printf("\n");
    }
    else
    {
        printf("NO\n");
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值