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