淺談期望的線性性(可加性)
感性理解一下
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;
}