期望的线性性(可加性)【CodeForces280c】【bzoj3036】【bzoj2134】

...好像题有点古老了 bzoj那道都不见了 都没法去交了 只好贴别人的代码了 大佬博客

 

Codeforces280c

题意 
给出一棵含n个白点的有根树,每次随机选择一个还没有被染黑的节点,将这个节点和这个节点子树中的所有点染黑. 
问期望操作多少次后所有点都被染黑. 
N<=100000

思路

只有删除掉1号点才算结束。考虑一个点被选中删除的概率。 
P(i)=\frac{1}{dep[i]},dep[i]表示i点的深度,其中1号根节点的深度为1. 
只有他到根路径上的点都没有被选中,他才能被选中。 
期望步数实际上就是选中的点的期望次数。 
所以E=\sum_{i=1}^{n}P\left ( i \right )=\sum_{i=1}^{n}\frac{1}{dep[i]}

#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=1e5+10;
int head[maxn],val[maxn*2],nxt[maxn*2];
int tot;
double ans=0;
void init()
{
	memset(head,-1,sizeof(head));
	tot=0;
}
void add(int u,int v)
{
	val[tot]=v;
	nxt[tot]=head[u];
	head[u]=tot++;
}
void dfs(int u,int f,int step)
{
	ans+=1.0/step;
	for(int i=head[u];i+1;i=nxt[i])
	{
		int v=val[i];
		if(v==f)
		continue;
		dfs(v,u,step+1);
	}
}
int main()
{
	init();
	int n;
	cin>>n;
	for(int i=1;i>a>>b;
		add(a,b);
		add(b,a);
	}
	dfs(1,1,1);
	printf("%.20lf\n",ans);
	return 0;
}

bzoj2134

题意

给出n道题目,每道题目有a[i]个选项,有一个人知道所有题目的正确选项,但是他把答案全部写在了第i+1的题目上(第n个题目的答案写在了第1个题目上),求出这个人做对题目的期望。

思路

首先对于a[i-1]和a[i]而言,假设要答对第i道题的话,那么概率就是min(a[i-1],a[i])/(a[i-1]*a[i])(a[i-1]*a[i]为方案总数)

但是a[i-1]*a[i]会暴int,所以我们简化为1.0/max(a[t],a[i]),就可以了

#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
int a[11000000];
double f[11000000];
int main()
{
    int n,A,B,C;
    scanf("%d%d%d%d%d",&n,&A,&B,&C,&a[1]);
    for(int i=2;i<=n;i++) a[i]=((LL)a[i-1]*A+B)%100000001;
    for(int i=1;i<=n;i++) a[i]=a[i]%C+1;
    for(int i=1;i<=n;i++)
    {
        int t=i-1;if(t==0) t=n;
        f[i]=f[t]+1.0/max(a[t],a[i]);
    }
    printf("%.3lf\n",f[n]);
    return 0;
}

bzoj3036绿豆蛙的归宿


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{每条边期望经过次数*边权} 
因为是有向无环图,所以 每条边的期望经过次数=该边起点的期望经过次数*从该起点出发经过该路径的概率。 
于是问题转成了求每个点的期望经过次数。很显然,每个点的期望经过次数=sigma{入边i的期望经过次数} 
于是发现边与点的期望值是相辅相成的关系,由于是有向无环图,所以拓扑排序就可以了

#include
#include
#include
#include
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 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;
}

 

你可能感兴趣的:(期望的线性性)