CF280C Game on Tree

CF280C Game on Tree

题意:

给定一个树,根节点为 \(1\),对于每一个操作,等概率的选择一个尚未被删去的节点,如果这个节点被选择,其子树也被删除。

删除到一号节点时停止,求删除的期望。

分析:

\(f_i\) 表示点 \(i\) 被选中的次数,则根据 期望的可加性 要求的答案为:

\[E[\sum f_i]=\sum E[f_i] \]

考虑 \(i\) 号节点选择的情况为:其祖先被选择都在 \(i\) 后面,否则就不会选到它。

因为 \(i\) 节点一共有 \(dep_i-1\) 个祖先,因此 \(i\) 节点排在这个序列最前面的概率是 \(\large\frac{1}{dep[i]}\)

因此,答案就是每个点深度分之一的加和。

代码:

#include<bits/stdc++.h>
#define db double 
using namespace std;
const db eps=1e-6;
const int N=1e5+5;
int n;
int dep[N],inv[N];
db ans;
vector<int> g[N];
void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    for(auto y:g[x]){
        if(y==fa) continue;
        dfs(y,x);
    }
}
int main(){
    cin>>n; 
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++) ans=ans+1.0*(1.0/dep[i]);
    printf("%.6lf\n",ans);
    // system("pause");
    return 0;
}

拓展:

正好今天模拟赛做到了关于这个结论的题目,想通过这个题目拓展一下:

题意:

有一条 \(1\)\(n\) 的链,给定 \(l\), \(r\) 每次从链上随机选一条边删除,如果删
除后 \(l\)\(r\) 不连通就停止,否则将剩余两部分中不包含 \(l\), \(r\) 的部分去掉,求期望删除的边数(去除的部分不算删除)。

\([l,r]\) 区间长度为 \(len\),则有两种情况:

  1. 删除 \([l,r]\) 区间的边,则直接无了,删除其中一条边的概率为 \(\frac{1}{len}\)
  2. 删除其他的边,此时,就可以看成上面一题的变式,但是,深度变成了距离这个区间的长度 \(k\)。删除这一条边的概率为 \(\frac{1}{len+k}\).

我们把整个 \([l,r]\) 区间上的边看成同一个点,那么这个点的初始深度就是 \(len\).

所以根据上面得出的结论,\([l,r]\) 的答案就是:

\[\sum_{i=len}^{l-1+len}\frac{1}{i}+\sum_{i=len}^{n-r+len}\frac{1}{i}+1 \]

代码:

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int n,m,inv[10000005],l,r;
int calc(int l,int r){
    return (inv[r]-inv[l-1]+mod)%mod;
}
int main(){
	freopen("divide.in","r",stdin); freopen("divide.out","w",stdout);
	cin>>n>>m;
	inv[1]=1;
	for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=2;i<=n;i++)inv[i]=(inv[i]+inv[i-1])%mod;
	while(m--){
		scanf("%d%d",&l,&r);
		printf("%d\n",(calc(r-l+1,r-1)+calc(r-l+1,n-l)+1)%mod);
	}
    system("pause");
    return 0;
}
posted @ 2021-11-08 20:10  Evitagen  阅读(39)  评论(0编辑  收藏  举报