yjc最近在學習樹的有關知識。今天,他遇到了這麼乙個概念:最近公共祖先。對於有根樹t的兩個結點u、v,最近公共祖先lca(t,u,v)表示乙個結點x,滿足x是u、v的祖先且x的深度盡可能大。yjc很聰明,他很快就學會了如何求最近公共祖先。他現在想尋找最近公共祖先有什麼性質,於是他提出了這樣的乙個問題:n層的滿k叉樹t,求對於每一對(i,j)(1≤i,j≤t的點數),lca(t,i,j)的深度的和是多少。這個數字n層的滿k叉樹指一棵帶標號的有根樹,深度為i(0≤i
對於30%的資料,滿足2≤n,k≤8;
對於50%的資料,滿足2≤n,k≤1000000;
對於100%的資料,滿足2≤n,k≤998244351。
顯然不是叫你寫lca吧。。。
對於每個節點我們考慮他的所有子節點能構成多少對
選取乙個節點x,設其所在子樹大小為size
乙個節點s能和不在同乙個子樹內的所有節點匹配,所以就有size*(k-1)/k種選擇方法
所以x的貢獻=deep[x]*size*size*(k-1)/2k
但是這樣不夠快,我們需要得到o(lg n)的做法
推導出(k-1)answer=σi*(k^(2n-i-1)-k^i)
繼續利用 σi*k^i =n*σk^i - σσk^j 和等比數列求和公式
我們得到
answer=k^2n-k-(2n-1)*k^n*(k-1)/(k-1)^3
可以用快速冪+逆元求解
完成(這就是一道數學計算題嘛)
#include
#define m 998244353
#define l long long
l pow(l x,int k)
int main()
JZOJ4918 最近公共祖先
給定一棵 n 個節點的有根樹,節點編號1到 n 根節點為 1號點。每個節點要麼是黑色要麼是白色,並且有權值wi 初始時所有節點都是白色的。現在總共有 m 個操作,分以下兩種 將節點 v 的顏色修改為黑色 給定 v 要求找到乙個黑色節點 u,最大化wl ca u v 如果此時樹上不存在黑色節點,輸出 ...
最近公共祖先 python 最近公共祖先
lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...