src:https://www.luogu.org/problemnew/show/P1654
解答:https://oi.men.ci/bzoj-4318/
方法同平方版本
思路:求期望,如求E(f[i]),我们要确定 f[ i ] 有几种可能,这里的可能就是pi和1-pi两种,然后各种情况的期望乘上各种情况的可能性大小
x表示i-1位置的连续长度,f[i-1] = E(x^3) f[i]-f[i-1]=E((x+1)^3)-E(x^3)=E(3*x^2+3*x+1)=3*E(x^2)+3*Ex+1
所以求f[i] , E(f[ i ]) = f[ i-1 ]*(1-p[i]) + (f[ i-1 ]+3*E(g[i-1]^2) + 3*E(g[i-1]) + 1)*p[i]
这里一定要搞明白的一点是f[i-1]是(Ex)^3还是E(x^3)!!!因为我们的计算目标是x^3,所以f[i-1]的期望是E(x^3)
讲解 E(x^3)为什么与(Ex)^3不同,假设x取到1 2 4的可能性分别为0. 3 0.3 0.4,那么Ex=1 * 0.3 + 2 * 0.3 + 4 * 0.4,而E(x^3)=1^3 * 0.3 + 2^3 * 0.3 + 4^3 * 0.4,很明显不是三次方关系嘛~~~
ac代码:
#include<bits/stdc++.h> using namespace std; #define per(i,a,b) for(int i=a;i <= b;i++) #define max(a,b) a=max(a,b) #define min(a,b) a=min(a,b) #define sz(x) (int)x.size() typedef long long ll; ll gcd(ll a,ll b){while(b){ll t=b;b=a%b;a=t;}return a;} const int inf=0x3f3f3f3f; const int mod=1000000007; #define siz 100001 double f[siz],p[siz];//g[siz]改成ex1和ex2,分别表示g[i]的一次和二次 double ex1[siz],ex2[siz]; int n; //f(i)表示以第i个字符结尾的期望得分,g(i)表示以第i个字符结尾连续的o的期望长度。 int main() { scanf("%d",&n); for(int i = 1;i <= n;i++){ scanf("%lf",&p[i]); ex1[i]=(ex1[i-1]+1)*p[i]; ex2[i]=(ex2[i-1]+2*ex1[i-1]+1)*p[i]; f[i]=f[i-1]+(3*ex2[i-1]+3*ex1[i-1]+1)*p[i]; } printf("%.1f\n",f[n]); return 0; }