EOJ Monthly 2018.11 C 租房(幾何數學)
阿新 • • 發佈:2019-01-25
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"); } }