Description
Solution
很明顯,如果兩個向量是反向的,那麼無論怎樣一定可以找到
首先有第一個結論:若向量
Proof.
設
則有
若是
若是
否則
還有第二個結論:向量
Proof
設
此時我們考慮
當
當
第三個結論:
Proof
∠BCD=∠AOB+∠OBC
有了這些結論,我們就可以解決這道題目了,不過要細心處理分類的條件(我被一個long long的平方坑了很長時間)。此外還有一些計算時候的小技巧。
- 向量的數量積:
|a||b|cosθ=x1∗x2+y1∗y2 - 判斷
max(∠BCD,∠BDC) :判斷E 的落點與CD 中點的關係。 k 的計算:數量積|a|2 (證明詳見這個博客)
Code
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define fo(i,a,b) for(i=a;i<=b;i++)
typedef long long ll;
ll x,y,xx,yy,ans1,ans2,ans;
ll dot,l1,l2,k;
bool bz;
ll sqr(ll x){return x*x;}
void deal(ll x,ll y,ll xx,ll yy,ll &ans1,ll &ans2){
ll dot=x*xx+y*yy,l1=sqr(x)+sqr(y),l2=sqr(xx)+sqr(yy);
//if(l1==0){bz=1;return;}
if(dot<0){
deal(x,y,-xx,-yy,ans1,ans2);ans2=-ans2;
return;
}
if(l1>l2){
deal(xx,yy,x,y,ans2,ans1);
return;
}
if(sqr(dot)*4<(l1*l2)|!l1){
ans1=1,ans2=0;
return;
}
ll k=dot/l1;
if(2*dot>l1*(2*k+1)){
deal(x,y,xx-(k+1)*x,yy-(k+1)*y,ans1,ans2);
ans1-=(k+1)*ans2;
}
else{
deal(x,y,xx-k*x,yy-k*y,ans1,ans2);
ans1-=k*ans2;
}
}
int main(){
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
while(scanf("%lld%lld%lld%lld",&x,&y,&xx,&yy)!=EOF){
ans=ans1=ans2=bz=0;
deal(x,y,xx,yy,ans1,ans2);
x*=ans1,y*=ans1,xx*=ans2,yy*=ans2;
ans=sqr(x+xx)+sqr(y+yy);
printf("%lld\n",ans);
}
}