数学期望

· · 个人记录

期望即每个可能发生的值乘以它的概率,求和

即值 x_1,x_2..x_n 对应概率 p_1,p_2...p_n

期望=\frac{x_1}{p_1}+\frac{x_2}{p_2}+..+\frac{x_n}{p_n}

例子: 13张牌,摸一次不是a陪1¥,摸到a得10¥,求期望

期望E(x)=\frac{1}{13}*10-\frac{12}{13}*1=-\frac{2}{13}

P4316 绿豆蛙的归宿

f_i为1~i的期望,d表所有路径,p表对应概率,即d_1(p_1),d_2(p_2)..d_n(p_n),一节点期望$E(x)= d_1p_1+d_2p_2+..+d_n*p_n

得 $$ E(x)=\sum_{i=1}^{n}d_1*p_1=\sum_{i \in son(x)}^{}(d_{son(i)}*p_{son(i)}+edge*p_{son(i)})*\frac{1}{out(i)} $$ 则 $$ E(x)=\sum_{i \in son(x)}^{}(E(i)+edge*p_{son(i)}*\frac{1}{out(i)}) $$ $$ P_x=\sum_{i \in son(x)}^{}P_i*\frac{1}{out(i)} $$ ``` #include<iostream> #include<cstdio> #include<queue> #include<vector> #define ll long long using namespace std; int n,m; struct e{ int v; ll w; }; vector<e> g[100005]; queue<int> q; int out[100005]; double f[100005]; ll ru[100005]; double p[100005]; void topu(){ q.push(1); p[1]=1; while(!q.empty()){ int u=q.front(); q.pop(); int k=g[u].size(); for(int i=0;i<k;++i){ int v=g[u][i].v; ru[v]--; f[v]+=(f[u]+g[u][i].w*p[u])/out[u]; p[v]+=p[u]/out[u]; if(!ru[v]) q.push(v); } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); g[u].push_back({v,w}); out[u]++; ru[v]++; } topu(); printf("%.2lf\n",f[n]); return 0; } ``` # [P8774 [蓝桥杯 2022 省 A] 爬树的甲壳虫](https://vjudge.net/contest/640254#problem/B) 设$f_i$为i爬到n的期望,答案为$f_0

f_i=1+P_{i+1}*f_0+(1-P_{i+1})*f_{i+1}

f_i必须有式子上的1,因为进行1步,且必定进行(概率为1),就是加了E=1/1

f_i要知道f_0,f_{i+1},带入求解 ,找规律

\begin{cases} f_0=1+P_1*f_0+(1-P_1)*f_1 ①\\ f_1=1+P_2*f_0+(1-P_2)*f_2 ②\\ f_2=1+P_3*f_0+(1-P_3)*f_3 ③\\ ....\\ \end{cases}

①式中只有f_0,f_1为变量,f_0为答案

f_0=1+P_1f_0+(1-P_1)(1+P_2f_0+(1-P_2)f_2)④$

化简 得

f_0=1+P_1*f_0+(1-P_1)+(1-P_1)*P_2*f_0+(1-P_1)(1-P_2)*f_2 ⑤ $f_0=1+P_1*f_0+(1-P_1)+(1-P_1)*P_2*f_0+(1-P_1)(1-P_2)*(1+P_3*f_0+(1-P_3)*f_3)

化简 得

f_0=1+P_1*f_0+(1-P_1)+(1-P_1)*P_2*f_0+(1-P_1)(1-P_2)+(1-P_1)(1-P_2)*P_3*f_0+(1-P_1)(1-P_2)(1-P_3)*f_3

将含P的项合并,含f的项合并

f_0=1+(1-P_1)+(1-P_1)(1-P_2)+f_0(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3)+(1-P_1)(1-P_2)(1-P_3)*f_3

再代入f_3...,一直代完f_n

f_0=1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1})+f_0(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n)+(1-P_1)(1-P_2)*....*(1-P_n)*f_n

因为f_0已到n,步数为0,so f_0=0

f_0=1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1})+f_0(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n)+(1-P_1)(1-P_2)*....*(1-P_n)*0

f_0=1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1})+f_0(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n) $(1-(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n))f_0=1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1}) f_0=\frac{1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1})}{1-(P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n)}

因为P_i=\frac{x_i}{y_i}是分数,又要取模,则要求出y_i 的逆元,用快速幂解决

关于逆元: 费马小定理:

a_{p-1}mod p=1,则a_{p-2} mod p=\frac{1}{a} \frac{x_i}{y_i}=x_i*(y_i)^{p-2}

关于取模: 设1+(1-P_1)+(1-P_1)(1-P_2)+....+(1-P_1)(1-P_2)*....*(1-P_{n-1})=x,\\ (P_1+(1-P_1)*P_2+(1-P_1)(1-P_2)*P_3+...+(1-P_1)(1-P_2)*....*(1-P_{n-1})*P_n)=y,则\\ f_0=\frac{x}{1-y},\\ 1-y取模p时要(1-y+p)\bmod p,

(1-P_i)先算P_i再减会导致取模错误,1-P_i=1-\frac{x_i}{y_i}=\frac{y_i-x_i}{y_i},算(y_i-x_i)*(y_i)^{p-2}即可

一定边算边取模!!

#include<iostream> 
#include<cstdio>
#define ll long long 
using namespace std;
const ll mod=998244353 ;
int n;
ll x[100005],y[100005];
ll c[100005];
ll s[100005];
ll inv(ll a){
    ll res=1;
    ll b=mod-2;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    } 
    return res;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%lld%lld",&x[i],&y[i]); 
        c[i]=(y[i]-x[i]+mod)%mod*inv(y[i])%mod;
    }
    s[0]=1;
    for(int i=1;i<=n;++i){
        s[i]=(s[i-1]*c[i])%mod;
    }
    ll fx=1;
    for(int i=1;i<n;++i){
        fx=(fx+s[i])%mod;
    }
    ll fy=x[1]*inv(y[1])%mod;
    for(int i=2;i<=n;++i){
        fy=(fy+s[i-1]*x[i]%mod*inv(y[i])%mod)%mod;
    }
    fy=(1-fy+mod)%mod;
    printf("%lld\n",fx*inv(fy)%mod);
    return 0;
} 

ボール

见题解

补充:一个串s,在i位置打了一下,就是在i上&0,其他位置&1,相当于s&(~(1<<(i-1)))

设串a,b,c为s串中朝x点投球后三种情况,

\begin{aligned} f_s &=1+\frac{f_a}{3}+\frac{f_b}{3}+\frac{f_c}{3} \\\end{aligned}

其中可能有一些串与s相同,设此串为a

\begin{aligned} f_s &=1+\frac{f_s}{3}+\frac{f_b}{3}+\frac{f_c}{3}\\ \frac{2}{3}*f_s=1+\frac{f_b}{3}+\frac{f_c}{3} \\\end{aligned}\\ f_s=\frac{2}{3}+\frac{f_b}{2}+\frac{f_c}{2}

设cnt个串与s相同

f_s=\frac{3}{3-cnt}*(1+(f..)/3),f..为与s不同的串的f的和

如果往0或15投的话可能投到-1或16,1/3的概率就浪费了,所以只需在[1,14]投就行了,手摸一下样例就行了

给double赋值max要

    memset(f,127,sizeof f);

或者for遍历赋值0x3f3f3f3f就行