[XSY3381] 踢罐子(几何)
XSY3381
點被選為點對之一的貢獻我們單獨計算(這部分貢獻的總和為4n(n?1)(n?2)4n(n-1)(n-2)4n(n?1)(n?2))。接下來只討論剩余部分的貢獻。
先把任意三個點構(gòu)成的六種選擇方案合并,發(fā)現(xiàn)在外接圓周和弦之間的點每個有2的貢獻,在外接圓上的點每個有1的貢獻。
然后考慮任意四個點A,B,C,DA,B,C,DA,B,C,D的貢獻。
發(fā)現(xiàn)當四個點構(gòu)成凸四邊形ABCDABCDABCD時,
若∠A+∠D=180°\angle A+\angle D=180\degree∠A+∠D=180°:
A,B,C,DA,B,C,DA,B,C,D四點共圓,即其中一個點在另外三個點構(gòu)成的三角形的外接圓上,因此A,B,C,DA,B,C,DA,B,C,D四個點每個有1的貢獻,A,B,C,DA,B,C,DA,B,C,D四點的貢獻為4。
若∠A+∠D<180°\angle A+\angle D<180\degree∠A+∠D<180°:
則必有∠B+∠C>180°\angle B+\angle C>180\degree∠B+∠C>180°。
DDD在△ABC\triangle ABC△ABC的外接圓外,選A,B,CA,B,CA,B,C為點對時,DDD無貢獻。同理AAA無貢獻。
BBB在△ACD\triangle ACD△ACD的外接圓弧和弦之間,選A,C,DA,C,DA,C,D為點對時,BBB有2的貢獻。同理CCC有2的貢獻。A,B,C,DA,B,C,DA,B,C,D四點的貢獻為4。
若∠A+∠D>180°\angle A+\angle D>180\degree∠A+∠D>180°:
則必有∠B+∠C<180°\angle B+\angle C<180\degree∠B+∠C<180°。類似上種情況。
當四個點構(gòu)成凹四邊形時,易證四個點產(chǎn)生的貢獻為0。
因此問題轉(zhuǎn)化為統(tǒng)計凸四邊形個數(shù)。
給出四個構(gòu)成凸四邊形的點,任選兩個點連邊,有4種情況剩下兩個點在連邊同側(cè),2種情況剩下兩個點在連邊異側(cè)。
給出四個構(gòu)成凹四邊形的點,任選兩個點連邊,有3種情況剩下兩個點在連邊同側(cè),3種情況剩下兩個點在連邊異側(cè)。
因此設(shè)整張圖中有aaa個凸四邊形,bbb個凹四邊形,
X=∑i<ji,j連邊,再無序地選兩個點,選的點在連邊同側(cè)的方案數(shù)X=\sum_{i<j}i,j連邊,再無序地選兩個點,選的點在連邊同側(cè)的方案數(shù)X=i<j∑?i,j連邊,再無序地選兩個點,選的點在連邊同側(cè)的方案數(shù)
Y=∑i<ji,j連邊,再無序地選兩個點,選的點在連邊異側(cè)的方案數(shù)Y=\sum_{i<j}i,j連邊,再無序地選兩個點,選的點在連邊異側(cè)的方案數(shù)Y=i<j∑?i,j連邊,再無序地選兩個點,選的點在連邊異側(cè)的方案數(shù)
可列出方程:
{4a+3b=X2a+3b=Y\begin{cases}4a+3b=X\\2a+3b=Y\end{cases}{4a+3b=X2a+3b=Y?
解得:
a=X?Y2a=\frac{X-Y}{2}a=2X?Y?
具體實現(xiàn)上,
對于每個點,把剩下的所有點按照和它的連線的斜率排序,求斜率可以用atan2latan2latan2l函數(shù)(加上lll避免爆精度)
然后,考慮兩個點的連線,設(shè)連線兩側(cè)的點數(shù)分別是LLL和RRR(注意這里要判斷,不能構(gòu)成了一個箭頭的形狀)
選兩個點在連線同側(cè)的有(L?1)L+(R?1)R2\frac{(L?1)L+(R?1)R}{2}2(L?1)L+(R?1)R?種情況,選兩個點在連線異側(cè)的有L×RL\times RL×R種情況。
時間復(fù)雜度O(n2logn)O(n^2logn)O(n2logn)
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define pi acos(-1) using namespace std; typedef long long ll; const int N=2010; int n,tot; double x[N],y[N],k[N]; ll ans=0; int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; } int main(){n=read();for(int i=1;i<=n;i++){x[i]=read();y[i]=read();}ans=4ll*n*(n-1)*(n-2);for(int i=1;i<=n;i++){tot=0;for(int j=1;j<=n;j++){if(i==j) continue;k[++tot]=atan2l(x[j]-x[i],y[j]-y[i]);if(k[tot]<0) k[tot]+=pi*2;}sort(k+1,k+tot+1);for(int j=1;j<=tot;j++){k[j+tot]=k[j]+pi*2;} for(int j=1,t=1;j<=tot;j++){while(t<=tot*2&&(k[t]<k[j]+pi)) t++;int l=t-j-1;int r=n-1-l-1;ans+=(1ll*l*(l-1)/2+1ll*r*(r-1)/2-1ll*l*r)*2ll;}}printf("%lld\n",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的[XSY3381] 踢罐子(几何)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何更改无线路由器密码 怎么修改无线路由
- 下一篇: 俄罗斯为何被禁止参加平昌冬奥会