1. 程式人生 > >EOJ Monthly 2018.11 C 租房(幾何數學)

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");
    }

}