给定一个
首先介绍一点前置知识:
正态分布:图形不再赘述,唯一需要注意的就是随机变量
概率密度函数:依然考虑一个随机变量
然后有个结论:正态分布的概率密度函数为:
关于这个东西的证明。。。完全不是人看的,似乎只能强行记下来这个公式。。。如果你一定要看一下证明,网上倒是也有一个 正态分布推导过程。
然后还有就是 C++ 库里自带了个 erf 和 erfc,大概求的是误差函数的积分和互补误差函数之类的,(我不会),有兴趣可以看看。
然后所以如果我们能够证明本题这玩意是正态分布的,那么就直接对这个
独立同分布:首先独立比较好理解,就是两个随机变量之间无影响,和高中数学里面的独立事件差不多。然后同分布就是指一些随机变量服从相同的分布。
Tips:概率论中
中心极限定理:对于
若
然后还有一个常用推论,当然首先我们需要知道正态分布的一点运算规则,即:
若
若
所以我们可以将刚才的中心极限定理式子转化为:
也就是说,本题里求的这些骰子的点数和,实际上就是
然后发现这东西套个自适应辛普森就可以在
但是我们不难发现这个东西还有点问题,就是中心极限定理需要一个前提,
显然对于
Tips:仅用多项式快速幂期望得分 60~70。
upd:上述过程就可以通过本题了,需要注意的一个问题是不要忘记在自适应辛普森的过程中限制层数,后文是我最开始写这道题时的因为没有限制层数的一些误区与另一种类似的方法,仅供参考。
如果不在自适应辛普森中限制层数,那么会有精度问题,原因除此之外还可能因拟合
总之还可以考虑另一个方法,即中心极限定理的初始式子:
不难发现我们知道了限定的 不过这样会发现依然是错误的如果在自适应辛普森中限制层数那么就没有问题了。
检查发现,对于正态分布中,在角落可能很小,从而导致
Tips:代码中注释部分即为后半部分的实现方式。
xxxxxxxxxx150123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
2223242526
27template < typename T = int >28inline T read(void);29
30int N, M;31
32comp comp_qpow(comp a, ll b){33 comp ret(1.0, 0.0), mul(a);34 while(b){35 if(b & 1)ret = ret * mul;36 b >>= 1;37 mul = mul * mul;38 }return ret;39}40
41class Polynomial{42private:43public:44 int len;45 comp A[2100000];46 comp Omega(int n, int k, bool pat){47 if(pat == DFT)return comp(cos(2 * PI * k / n), sin(2 * PI * k / n));48 return conj(comp(cos(2 * PI * k / n), sin(2 * PI * k / n)));49 }50 void Reverse(comp* pol){51 int pos[len + 10];52 memset(pos, 0, sizeof pos);53 for(int i = 0; i < len; ++i){54 pos[i] = pos[i >> 1] >> 1;55 if(i & 1)pos[i] |= len >> 1;56 }57 for(int i = 0; i < len; ++i)if(i < pos[i])swap(pol[i], pol[pos[i]]);58 }59 void FFT(comp* pol, int len, bool pat){60 Reverse(pol);61 for(int siz = 2; siz <= len; siz <<= 1)62 for(comp* p = pol; p != pol + len; p += siz){63 int mid = siz >> 1;64 for(int i = 0; i < mid; ++i){65 auto tmp = Omega(siz, i, pat) * p[i + mid];66 p[i + mid] = p[i] - tmp, p[i] = p[i] + tmp;67 }68 }69 if(pat == IDFT)70 for(int i = 0; i <= len; ++i)71 A[i].real(A[i].real() / (ld)len), A[i].imag(A[i].imag() / (ld)len);72 }73 void MakeFFT(void){74 FFT(A, len, DFT);75 for(int i = 0; i < len; ++i)A[i] = comp_qpow(A[i], N);76 FFT(A, len, IDFT);77 }78}poly;79
80ld mu, sigma2;81
82ld f(ld x){83 return exp(-(x - mu) * (x - mu) / 2.0 / sigma2) / sqrt(2.0 * PI * sigma2);84}85ld Simpson(ld a, ld b){86 return (b - a) * (f(a) + f(b) + 4 * f((a + b) / 2.0)) / 6.0;87}88ld Adaptive(ld l, ld r, ld cur, ld eps = 1e-6, ll dep = 1){89 ld mid = (l + r) / 2.0;90 ld lval = Simpson(l, mid), rval = Simpson(mid, r);91 if(dep >= 10 && fabs(lval + rval - cur) <= eps * 15.0)return lval + rval + (lval + rval - cur) / 15.0;92 return Adaptive(l, mid, lval, eps / 2.0, dep + 1) + Adaptive(mid, r, rval, eps / 2.0, dep + 1);93}94
95int main(){96 int T = read();97 while(T--){98 M = read(), N = read();99 if(N * M <= (int)1e5){100 memset(poly.A, 0, sizeof poly.A);101 for(int i = 0; i <= M - 1; ++i)102 poly.A[i].real((ld)1.0 / (ld)M), poly.A[i].imag(0.0);103 poly.len = 1;104 while(poly.len <= N * M)poly.len <<= 1;105 poly.MakeFFT();106 for(int i = 1; i <= 10; ++i){107 int A = read(), B = read();108 ld ans(0.0);109 for(int j = A; j <= B; ++j)ans += poly.A[j].real();110 printf("%.10Lf\n", ans);111 }112 }else{113 // mu = 0.0, sigma2 = 1.0;114 // ld real_mu = (ld)(M - 1) / 2.0;115 // ld real_sig = ((ld)M * M - 1.0) / 12.0;116 // for(int i = 1; i <= 10; ++i){117 // int A = read(), B = read();118 // ld L = (ld)((ld)A - N * real_mu) / sqrt(N * real_sig);119 // ld R = (ld)((ld)B - N * real_mu) / sqrt(N * real_sig);120 // printf("%.8Lf\n", Adaptive((ld)L, (ld)R, Simpson(L, R)));121 // // printf("%.8Lf\n", Adaptive((ld)0, (ld)R, Simpson(0, R)) - Adaptive((ld)0, (ld)L, Simpson(0, L)));122 // }123
124 mu = (ld)N * (ld)(M - 1) / 2.0;125 sigma2 = (ld)N * (ld)((ll)M * M - 1) / 12.0;126 for(int i = 1; i <= 10; ++i){127 int A = read(), B = read();128 printf("%.8Lf\n", Adaptive((ld)A, (ld)B, Simpson(A, B)));129 }130 }131 }132 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);133 return 0;134}135
136template < typename T >137inline T read(void){138 T ret(0);139 int flag(1);140 char c = getchar();141 while(c != '-' && !isdigit(c))c = getchar();142 if(c == '-')flag = -1, c = getchar();143 while(isdigit(c)){144 ret *= 10;145 ret += int(c - '0');146 c = getchar();147 }148 ret *= flag;149 return ret;150}update-2022_12_10 初稿
update-2023_02_01 fix 初稿中的一些错误与不严谨的表述