B 2D Internet Angel
B 题题意:给定内外同心圆,半径分别为 R1,R2,沿内侧圆外有一 n 边外接多边形 {Pi},与内侧圆的切点为 {Qi},保证这一多边形完全在外侧圆内。记此外接多边形外与外侧圆内侧部分的点到多边形和内侧圆切点的最近距离为 X,求 E(X2)。n≤1×105。
解法:过凸包顶点 Pi(xi,yi) 和 Pi+1(xi+1,yi+1) 的中点 Qi,和外侧圆弧(即 FP2Q2E)所包络区域内的点的最近距离是到 Qi 点的距离。记 Pi 极角为 βi,Qi 极角为 αi,设一点位于 U(x,y),则利用 ΔUOQ 的余弦定理,设 ∠PiOU=θ,∠UOQi=αi−βi−θ,则有 UQ22=OU2+OQ22−2OU⋅OQ2cos(αi−βi−θ),因而只与 OU=r 和极角 θ 有关,因而可以利用极坐标下二重积分,计算出对于 Qi 答案为:
gi=2∫0αi−βidθ∫R1sec(αi−βi−θ)R2(R12+r2−2R1rcos(αi−βi−θ))rdr

二倍的原因在于 ∠PiOQi=∠QiOPi+1。
考虑计算如下的二重积分:
f(α)====∫0αdθ∫R1secθR2(R12+r2−2R1rcosθ)rdr∫0αdθ(2R12r2+41r4−32R1r3cosθ)∣∣∣∣R1secθR2α(2R12R22+41R24)−4R14∫0α2sec2θ+sec4θdθ−32R1R23∫0αcosθdθ+32R14∫0αsec2θdθα(2R12R22+41R24)−12cos2αR14tanα−32R1R23sinα
因而可以 O(1) 的计算出每个 Qi 的答案。最后只需要使用直线与直线的交算出 Pi,得到凸多边形 C={Pn} 然后求出其面积 S,答案为 πR22−SC∑i=1ngi。
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d%Lf%Lf", &n, &r1, &r2);
vector<Point> Q(n), P(n);
vector<int> angQ(n);
for (int i = 0, x; i < n;i++)
{
scanf("%d", &x);
angQ[i] = x;
Q[i].x = r1 * cosl(x * PI / 10000);
Q[i].y = r1 * sinl(x * PI / 10000);
}
for (int i = 0; i < n;i++)
{
Line now;
now.p = Q[i];
now.v = (Point){-Q[i].y, Q[i].x};
Line nx;
nx.p = Q[(i + 1) % n];
nx.v = (Point){-Q[(i + 1) % n].y, Q[(i + 1) % n].x};
P[i] = nx.inter(now);
}
auto inner = convexhull(P);
auto cal_ang = [&](int id)
{
return atan2l(P[id].y, P[id].x);
};
long double ans = 0;
for (int i = 0; i < n;i++)
{
long double nowQ = angQ[i] * PI / 10000;
long double prevP = cal_ang((i + n - 1) % n);
long double nowP = cal_ang(i);
while(prevP > nowQ)
prevP -= PI;
while(nowP < nowQ)
nowP += PI;
ans += f(nowP - nowQ) + f(nowQ - prevP);
}
printf("%.15Lf\n", ans / (r2 * r2 * PI - inner.area() / 2));
}
return 0;
}