利用斯特林数转下降幂的技巧,再求期望。
单纯求 $x^3$ 的期望比较简单,两次差分即可。考虑加强一下,求 $x^m$ 的期望。用二项式定理拆开求每一项可以做到 $\mathcal O(nm^2)$。
还能做到更优吗?我们发现直接求 $x^m$ 的期望是非常困难的。考虑拆开,但不是用二项式定理,而是利用斯特林数转下降幂的技巧:
对于每个 $k$ 求 $x^{\underline k}$ 的期望最后乘上系数得到答案。时间复杂度 $\mathcal O(m^2+nm)$。
实际上,还有一种办法避免求逆元,将 $x^{\underline  k}$ 转化为 $k!\binom{x}{k}$,即求 $\binom{x}{k}$ 的期望。过程中可以根据 $\binom{x}{k}=\binom {x-1}{k-1}+\binom{x-1}{k}$ 直接递推即可(二者本质上是一样的)。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
   | #include<iostream> #include<cstdio> using namespace std; const int N=1e5+10,M=10; template<class T> inline void read(T &x) {     x=0;int f=0;     char ch=getchar();     while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}     while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();     if(f)x=~x+1; } template<class T,class ...T1> inline void read(T &x,T1 &...x1) {     read(x),read(x1...); } int n,m; double p,a[N],b[N]; int fac[M],s[N][M]; int main() {     read(n);     m=3;     fac[0]=1;     for(int i=1;i<=m;i++)fac[i]=fac[i-1]*i;     s[0][0]=1;     for(int i=1;i<=m;i++)         for(int j=1;j<=i;j++)             s[i][j]=s[i-1][j-1]+j*s[i-1][j];     for(int i=1;i<=n;i++,b[1]+=(a[1]=p))     {         scanf("%lf",&p);         for(int j=m;j>1;j--)a[j]+=a[j-1],a[j]*=p,b[j]+=a[j];     }     double ans=0;     for(int i=1;i<=m;i++)ans+=b[i]*fac[i]*s[m][i];     printf("%.1lf",ans);     return 0; }
   |