F. 一个经典概率问题

思路

这里提供一个好想好实现不用积分的方法

假设把圆分成两个区域,一个圆心为 OO 半径为 0.50.5 的圆,一个是半径为 11 中间的空心是半径0.50.5 的圆的一个环,两者面积是 0.25π0.25π0.75π0.75π那么B的选法落在环上概率比落在圆上的概率肯定更大,那么这样得到的弦长就会比以半径中点形成的弦长小(因为随着落点远离圆心形成的弦长是个递减过程)两者之比是 3:13:1。所以最终比界限小弦长数量应该更多的。

而L的选法是随机在一条半径上选一点,弦长与哪条半径上无关,只与离圆心的距离有关,于是我们就可以得出L方法形成的弦长落在以半径中点形成弦长两端的概率相等,两者之比是 1:11:1

于是最终我们只需要比较弦长,落在以半径中点形成弦长的两端那边多即可。

不过需要注意的是,因为L的选法是均分,所以概率上来讲是有可能导致落在更小区域的更多,所以不能直接这样判断,需要给定一个值偏离太多才判定为B的选法(博主自己就是忘记设定偏离值将部分L错判为B).

代码

#include <bits/stdc++.h>
using namespace std;

const double N = 1e5;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    double c = 1.0 / N;
    double r = c * 5e4; // 也可以直接用0.5
    double mid = 2.0 * sqrt(1 - r * r); // 以半径中点形成的弦长

    int n;
    cin >> n;
    int sum1 = 0, sum2 = 0;
    for(int i = 1; i <= n; i ++){
        double x; cin >> x;
        if(x - mid > 1e-6) sum2 ++;
        else sum1 ++;
    }
    
    if(sum2 + 10000 < sum1) cout << "B"; // 记得要设定偏离值
    else cout << "L"; 
    return 0;
}

法二思路

从别的博客那里学了一手法二,通过积分的方法可以确定,L方法 OBOB 长度的平均值为 0.50.5, B方法平均值为 2/32/3。将给出的弦长换算出 OBOB 长,求出平均值看更接近哪一个

法二代码

#include <bits/stdc++.h>
using namespace std;

const double N = 1e6;

/*
L方法每次在一条半径上随机选点p, 那么op的平均长度就是0.5
B方法积分求解后平均长度是2/3
算出平均值后看与那个更接近
*/
int main(){
    int n;
    cin >> n;
    double sum = 0;
    for(int i = 1; i <= n; i ++){
        double x; cin >> x; x /= 2.0;
        sum += sqrt(1 - x * x); 
    }
    sum /= (double)n;
    double x1 = fabs(sum - 0.5);
    double x2 = fabs(sum - 0.6666666);
    if(x1 < x2) cout << "L";
    else cout << "B";
    return 0;
}