bzoj1913: [Apio2010]signaling 信号覆盖

传送门
我们发现凸四边形贡献为2,凹四边形贡献为1
而且四边形总个数=C(n,4)
所以我们只要知道凹四边形的个数就可以了
我们枚举在凹四边形中内角大于180的点
然后我们将其他点按照极角序排序
枚举极角差刚刚不小于π的两条边
那么这两条边之间的点和其中一条边上的点不包含中间点。
由于按照极角排序,那么枚举的时间复杂度是O(n)。
设p为不包含中间点的三角形个数,那么以该点为中间点的凹四边形个数为C(n-1,3)-p。
最后的期望即为(a+2*b)/C(n,3)。

#include<cstdio> 
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 1505
#define pi 3.1415926535898
#define ll long long
using namespace std;
struct point{double x,y;}a[N];
double ang[N*2];
ll tu,ao,tot;
int top,n,t;
ll C(ll n,ll m){
    if (m==2) return n*(n-1)/2;
    if (m==3) return n*(n-1)*(n-2)/6;
    return n*(n-1)*(n-2)*(n-3)/24;
}
void calc(int x){
    top=0;
    for (int i=1;i<=n;i++)
        if (i!=x)
            ang[++top]=atan2(a[i].y-a[x].y,a[i].x-a[x].x);
    sort(ang+1,ang+top+1);
    tot=0;
    t=top;
    for (int i=1;i<=t;i++) ang[++top]=ang[i]+2*pi;
    int p=1;
    for (int i=1;i<=t;i++){
        p=max(p,i+1);
        while (p<=top&&ang[p]<ang[i]+pi) p++;
        if (p-i-1>=2) tot+=C(p-i-1,2);
    }
    ao+=C(n-1,3)-tot;
}
int main(){
    scanf("%d",&n);
    if (n<=3){printf("0"); return 0;}
    for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
    for (int i=1;i<=n;i++) calc(i);
    tu=C(n,4)-ao;
    printf("%lf",(double)(ao+tu*2)/C(n,3)+3);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值