B 2D Internet Angel

B 题题意:给定内外同心圆,半径分别为 R1,R2R_1,R_2,沿内侧圆外有一 nn 边外接多边形 {Pi}\{P_i\},与内侧圆的切点为 {Qi}\{Q_i\},保证这一多边形完全在外侧圆内。记此外接多边形外与外侧圆内侧部分的点到多边形和内侧圆切点的最近距离为 XX,求 E(X2)E(X^2)n1×105n \leq 1\times 10^5

解法:过凸包顶点 Pi(xi,yi)P_i(x_i,y_i)Pi+1(xi+1,yi+1)P_{i+1}(x_{i+1},y_{i+1}) 的中点 QiQ_{i},和外侧圆弧(即 FP2Q2EFP_2Q_2E)所包络区域内的点的最近距离是到 QiQ_i 点的距离。记 PiP_i 极角为 βi\beta_iQiQ_i 极角为 αi\alpha_i,设一点位于 U(x,y)U(x,y),则利用 ΔUOQ\Delta UOQ 的余弦定理,设 PiOU=θ\angle P_iOU=\thetaUOQi=αiβiθ\angle UOQ_i=\alpha_i-\beta_i-\theta,则有 UQ22=OU2+OQ222OUOQ2cos(αiβiθ)UQ_2^2=OU^2+OQ_2^2-2OU\cdot OQ_2 \cos(\alpha_i-\beta_i-\theta),因而只与 OU=rOU=r 和极角 θ\theta 有关,因而可以利用极坐标下二重积分,计算出对于 QiQ_i 答案为:

gi=20αiβidθR1sec(αiβiθ)R2(R12+r22R1rcos(αiβiθ))rdrg_i=2\int_{0}^{\alpha_i-\beta_i} {\rm d}\theta\int_{R_1\sec (\alpha_i-\beta_i-\theta)}^{R_2} (R_1^2+r^2-2R_1r\cos (\alpha_i-\beta_i-\theta))r{\rm d}r

alt

二倍的原因在于 PiOQi=QiOPi+1\angle P_iOQ_i=\angle Q_iOP_{i+1}

考虑计算如下的二重积分:

f(α)=0αdθR1secθR2(R12+r22R1rcosθ)rdr=0αdθ(R12r22+14r42R1r33cosθ)R1secθR2=α(R12R222+14R24)R1440α22θ+4θdθ2R1R2330αcosθdθ+2R1430α2θdθ=α(R12R222+14R24)R14tanα122α23R1R23sinα\begin{aligned} f(\alpha)=&\int_{0}^{\alpha}{\rm d}\theta\int_{R_1\sec\theta}^{R_2} (R_1^2+r^2-2R_1r\cos \theta)r{\rm d}r\\ =&\int_{0}^{\alpha}{\rm d}\theta \left .\left(\dfrac{R_1^2r^2}{2}+\dfrac{1}{4}r^4-\dfrac{2R_1r^3}{3}\cos \theta\right)\right |_{R_1\sec \theta}^{R_2}\\ =&\alpha\left(\dfrac{R_1^2R_2^2}{2}+\dfrac{1}{4}R_2^4\right)-\dfrac{R_1^4}{4}\int_{0}^{\alpha}2\sec^2 \theta+\sec^4 \theta{\rm d}\theta-\dfrac{2R_1R_2^3}{3}\int_{0}^{\alpha}\cos \theta{\rm d}\theta+\dfrac{2R_1^4}{3}\int_{0}^{\alpha}\sec^2 \theta{\rm d}\theta\\ =&\alpha\left(\dfrac{R_1^2R_2^2}{2}+\dfrac{1}{4}R_2^4\right)-\dfrac{R_1^4\tan \alpha}{12\cos^ 2\alpha}-\dfrac{2}{3}R_1R_2^3\sin \alpha \end{aligned}

因而可以 O(1)\mathcal O(1) 的计算出每个 QiQ_i 的答案。最后只需要使用直线与直线的交算出 PiP_i,得到凸多边形 C={Pn}C=\{P_n\} 然后求出其面积 SS,答案为 i=1ngiπR22SC\displaystyle \dfrac{\sum_{i=1}^n g_i}{\pi R_2^2-S_C}

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;
}