2019徐州网络赛 Random Access Iterator (概率dp)
设计dp状态为f[i]表示以i为根的子树能到达正确答案的概率是多少,那么f[1]就是答案
当我们先行计算出他儿子的答案时,根据独立性以及反方向考虑,我们只需要知道一次不能到达正确答案的概率,之后重复size遍,用1去减就是答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int inf=0x3f3f3f3f; const int N=2e6+10; const int mod=1e9+7; int h[N],ne[N],e[N],idx; int depth[N]; int sign[N]; int f[N],sz[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } ll qmi(ll a,ll b){ ll res=1; while(b){ if(b&1){ res=res*a%mod; } b>>=1; a=a*a%mod; } return res; } void dfs(int u,int sum,int fa){ int i; sign[u]=sum; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; sz[u]++; dfs(j,sum+1,u); sign[u]=max(sign[u],sign[j]); } } void dfs1(int u,int fa){ int i; ll sum=0; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; if(sign[j]==sign[1]){ dfs1(j,u); sum=(sum+f[j])%mod; } } if(sz[u]==0){ f[u]=1; return ; } else{ ll cnt=(1-sum*qmi(sz[u],mod-2)+mod)%mod; f[u]=(1-qmi(cnt,sz[u])+mod)%mod; return ; } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; int n; cin>>n; for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); } dfs(1,1,-1); dfs1(1,-1); cout<<f[1]<<endl; return 0; }
没有人不辛苦,只有人不喊疼