浅谈期望的线性性(可加性)
浅谈期望的线性性(可加性)
感性理解一下
E(X+Y)=E(X)+E(Y)
即两个(或多个)随机变量的和的期望等于期望的和
理论解释
如果不想看或者看不懂把规律记住
当然如果要理解透彻,那么就要练题
http://codeforces.com/problemset/problem/280/C
题目大意:
给定一棵有根树,每次随机选一个未被删除的点,将以它为根的子树删除。
求删除整棵树所用的期望步数。
solution:
初看每一个点被选它自己而被染色到的概率都是1/n,
但仔细想想就会发现,某一个点对答案的贡献只与这个点有多少个祖先有关。
因为如果这个点会被选到,当且仅当它的所有祖先都没有被选到
所有每个点被选而被染色的概率为1/deep[i]。
由期望的线性性
我们是不是可以计算出 每个点被染黑的期望操作次数,然后相加就是整棵树的了
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200003
using namespace std;
int n,tot,point[N],nxt[N],v[N],dep[N];
void add(int x,int y)
{
tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1;
for (int i=point[x];i;i=nxt[i]){
if (v[i]==fa) continue;
dfs(v[i],x);
}
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<n;i++) {
int x,y; scanf("%d%d",&x,&y);
add(x,y);
}
dfs(1,0);
double ans=0;
for (int i=1;i<=n;i++)
ans+=(double)(1.0/dep[i]);
printf("%.9lf\n",ans);
}
https://www.luogu.org/problem/P4316
Description
随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度。绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
Input
第一行: 两个整数 N M,代表图中有N个点、M条边
第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边
Output
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
Sample Input
4 4
1 2 1
1 3 2
2 3 3
3 4 4
Sample Output
7.00
HINT
对于100%的数据 N<=100000,M<=2*N
由期望的线性性可得:
经过路径期望总长度=sigma{每条边期望经过次数*边权}
每条边的期望经过次数=该边起点的期望经过次数*从该起点出发经过该路径的概率
问题转成了求每个点的期望经过次数
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100000+5;
int n,m,in[N],out[N];
int head[N],end[N*2],len[N*2],nxt[N*2],hh=0;
queue<int> q;
double p[N],ans=0;
void adde(int a,int b,int c){
hh++;
end[hh]=b;
len[hh]=c;
nxt[hh]=head[a];
head[a]=hh;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
adde(a,b,c);
in[b]++,out[a]++;
}
q.push(1);
p[1]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=nxt[i]){
int v=end[i];
ans+=p[u]/out[u]*len[i];
p[v]+=p[u]/out[u];
in[v]--;
if(in[v]==0){
q.push(v);
}
}
}
printf("%.2lf",ans);
return 0;
}
再说一道睿(正)智(睿)今天考试题,作为T1,哼哼,当然没A
分析:
对于ai=1的情况,很显然就是(1+2+3+.....+n)/n
考虑a1在1到n个不同的位置,其他的数有(n-1)!的排列,这样价值就是(1+2+3+4++++n)*(n-1)!
又因为有n!种排列所以就是(1+2+3+.....+n)/n
回到正题
code:
#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
int f=1;char k=getchar();x=0;
for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
x*=f;
}
template<class T>il _print(T x){
if(x/10) _print(x/10);
putchar(x%10+'0');
}
template<class T>il print(T x){
if(x<0) putchar('-'),x=-x;
_print(x);
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
int res=1,bas=x%mod;
while(m){
if(m&1) res=(1ll*res*bas)%mod;
bas=(1ll*bas*bas)%mod,m>>=1;
}
return res%mod;
}
const int MAXN = 1e5+5;
int n,bas,val,mx;
double ans=1;
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n);
read(bas);
for(ri i=2;i<=n;++i){
read(val);
ans+=val*1./(val+bas);
}
printf("%.10f",ans);
return 0;
}