「BZOJ1913」[Apio2010] signaling 信号覆盖
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
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。
题解
pyc:
题目大意:一个平面上n个点,随机选3个点构成一个圆,问期望有多少个点在这个圆内和圆上。数据保证没有4点共圆、3点共线和重点。
算法讨论:考虑四边形,凸四边形对答案的贡献为2,凹四边形对答案的贡献为1。设凹四边形个数为a,凸四边形个数为b,那么b=C(n,4)-a。枚举凹四边形的中间点,以中间点为原点,把其他点按照极角排序,枚举极角差刚刚不小于π的两条边,那么这两条边之间的点和其中一条边上的点不包含中间点。由于按照极角排序,那么枚举的时间复杂度是O(n)。设p为不包含中间点的三角形个数,那么以该点为中间点的凹四边形个数为C(n-1,3)-p。最后的期望即为(a+2*b)/C(n,3)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
#include<set> #include<map> #include<ctime> #include<queue> #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define pi acos(-1) #define inf 2147483647 #define ll long long using namespace std; 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; } ll A,B,n; struct P{ ll x,y; double angel; friend ll operator*(P a,P b){ return a.x*b.y-a.y*b.x; } friend P operator-(P a,P b){ return (P){a.x-b.x,a.y-b.y}; } friend double atan2(P a){ return atan2(a.y,a.x); } }a[1505],p[1505]; bool operator<(P a,P b) { return a.angel<b.angel; } ll solve(int x) { ll tot=(n-1)*(n-2)*(n-3)/6; int top=0; for(int i=1;i<=n;i++) { if(i!=x)p[++top]=a[i]; else p[0]=a[i]; } for(int i=1;i<=top;i++)p[i].angel=atan2(p[i]-p[0]); sort(p+1,p+top+1); int R=2,t=0; for(int i=1;i<=top;i++) { while((p[i]-p[0])*(p[R]-p[0])>=0) { R=R%top+1;t++; if(R==i)break; } tot-=t*(t-1)/2; t--; } return tot; } int main() { n=read(); if(n==3){puts("3.00");return 0;} for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); for(int i=1;i<=n;i++)A+=solve(i); B=n*(n-1)*(n-2)*(n-3)/24-A; double ans=2*B+A; ans/=n*(n-1)*(n-2)/6; printf("%.6lf",ans+3); return 0; } |
Subscribe