【2020.11.25提高組模擬】樹的解構(deconstruct) 題解
阿新 • • 發佈:2020-11-25
【2020.11.25提高組模擬】樹的解構(deconstruct) 題解
題目描述
給一棵以\(1\)為根的外向樹,進行\((n-1)\)次刪邊操作,每次都會從沒有刪掉的邊中等概率地刪掉一條邊\(a\to b\),代價是\(b\)的子樹大小。刪去這條邊後\(b\)為根的子樹會形成一棵新的以\(b\)為根的有根外向樹。求進行\(n-1\)次操作後期望的代價總和是多少,對\(10^9+7\)取模。
\(n\le2\times10^6\)。
Solution
題解中有兩個解決方案,我暫且只看懂了\(\texttt{Alternative Solution}\),就先記錄這種吧。
對每個點x考慮計算貢獻。當\(x\)
所以
\[ans=\sum_{i=1}^n\sum_{j=1}^{dep_i}\frac1j \]線性(或加個\(\log\)也行)預處理出\(\frac1j\)
注意別用\(dfs\),會爆棧\(RE\)。
Code
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include<set> #include<queue> #include<vector> #define IL inline #define re register #define LL long long #define ULL unsigned long long #ifdef TH #define debug printf("Now is %d\n",__LINE__); #else #define debug #endif using namespace std; template<class T>inline void read(T&x) { char ch=getchar(); int fu; while(!isdigit(ch)&&ch!='-') ch=getchar(); if(ch=='-') fu=-1,ch=getchar(); x=ch-'0';ch=getchar(); while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} x*=fu; } inline LL read() { LL x=0,fu=1; char ch=getchar(); while(!isdigit(ch)&&ch!='-') ch=getchar(); if(ch=='-') fu=-1,ch=getchar(); x=ch-'0';ch=getchar(); while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*fu; } int G[55]; template<class T>inline void write(T x) { int g=0; if(x<0) x=-x,putchar('-'); do{G[++g]=x%10;x/=10;}while(x); for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n'); } int n; int head[2000010],ver[2000010],nxt[2000010]; int cnt; int depth[2000010],fa[2000010]; void insert(int x,int y) { nxt[++cnt]=head[x]; ver[cnt]=y; head[x]=cnt; } void dfs(int x) { for(int i=head[x];i;i=nxt[i]) { dfs(ver[i]); depth[ver[i]]=depth[x]+1; } } void bfs()//出題人不講武德 dfs怎麼了? 惹你了? (doge) { queue<int>q; q.push(1); while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=nxt[i]) q.push(ver[i]),depth[ver[i]]=depth[x]+1; } } #define p 1000000007 LL inv[2000010]; IL LL qpow(LL a,LL b) { LL ans=1; while(b) { if(b&1) ans=ans*a%p; a=a*a%p; b>>=1; } return ans; } LL ans; int main() { // freopen("deconstruct.in","r",stdin); // freopen("deconstruct.out","w",stdout); n=read(); for(re int i=1;i<=n;i++) inv[i]=(qpow(i,p-2)+inv[i-1])%p; for(re int i=2;i<=n;i++) insert(fa[i]=read(),i); bfs(); for(re int i=1;i<=n;i++) ans=(ans+inv[depth[i]])%p; write(ans); return 0; }