[BZOJ1913][APIO2010]信号覆盖(计算几何+计数)

1913: [Apio2010]signaling 信号覆盖

Time Limit: 20 SecMemory Limit: 64 MB
Submit: 1658Solved: 672
[Submit][Status][Discuss]

Description

Input

输入第一行包含一个正整数 n, 表示房子的总数。接下来有 n 行,分别表示每一个房子的位置。对于 i = 1, 2, .., n, 第i 个房子的坐标用一对整数 xi和yi来表示,中间用空格隔开。

Output

输出文件包含一个实数,表示平均有多少个房子被信号所覆盖,需保证输出结果与精确值的绝对误差不超过0.01。

Sample Input

4
0 2
4 4
0 0
2 0

Sample Output

3.500

HINT

3.5, 3.50, 3.500, … 中的任何一个输出均为正确。此外,3.49, 3.51,
3.499999,…等也都是可被接受的输出。
【数据范围】
100%的数据保证,对于 i = 1, 2, .., n, 第 i 个房子的坐标(xi, yi)为整数且
–1,000,000 ≤ xi, yi ≤ 1,000,000. 任何三个房子不在同一条直线上,任何四个房子不
在同一个圆上;
40%的数据,n ≤ 100;
70%的数据,n ≤ 500;
100%的数据,3 ≤ n ≤ 1,500。

Source

[Submit][Status][Discuss]

场上绝对想不到系列。https://blog.csdn.net/regina8023/article/details/45556321

1 #include<cmath>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const double Pi=acos(-1.);
 9 const int N=2010;
10 struct P{ double x,y; }p[N];
11 double a[N<<1];
12 int n;
13 
14 ll C(int n,int m){
15     ll ans=1;
16     rep(i,1,m) ans=1ll*ans*(n-i+1);
17     rep(i,2,m) ans/=i;
18     return ans;
19 }
20 
21 int main(){
22     freopen("signaling.in","r",stdin);
23     freopen("signaling.out","w",stdout);
24     scanf("%d",&n); ll t=0;
25     rep(i,1,n) scanf("%lf%lf",&p[i].x,&p[i].y);
26     rep(i,1,n){
27         int tot=0;
28         rep(j,1,n) if (j!=i){
29             a[++tot]=atan2(p[j].y-p[i].y,p[j].x-p[i].x);
30             if (a[tot]<0) a[tot]+=Pi*2;
31         }
32         sort(a+1,a+n);
33         rep(j,1,n-1) a[n-1+j]=a[j]+2*Pi;
34         ll x=0; int now=1;
35         rep(j,1,n-1){
36             while (now<(n-1)*2 && a[now+1]-a[j]<Pi) now++;
37             if (now-j>1) x=x+C(now-j,2);
38         }
39         t=t+C(n-1,3)-x;
40     }
41     double ans=(double)(t+(C(n,4)-t)*2)/C(n,3)+3;
42     printf("%.6lf\n",ans);
43     return 0;
44 }