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\),则有两种情况:
- 删除 \([l,r]\) 区间的边,则直接无了,删除其中一条边的概率为 \(\frac{1}{len}\)
- 删除其他的边,此时,就可以看成上面一题的变式,但是,深度变成了距离这个区间的长度 \(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;
}
不关注的有难了😠😠😠https://b23.tv/hoXKV9