樹分治 BZOJ 2152 聰聰可可

2021-06-29 01:10:34 字數 1468 閱讀 2797

考慮經過根的路徑,不經過根的路徑由分治得出。記子樹中的所有點到根的路徑長度對3取模以後為0的個數為a,為1的個數為b,為2的個數為c。。。。組合數學容易算出路徑條數為a * a + b * c * 2。。。然後計算概率即可。。。

#include #include #include #include #include #include #include #include #include #include #include #include #include #define maxn 20005

#define maxm 40005

#define eps 1e-7

#define mod 1000000007

#define inf 0x3f3f3f3f

#define pi (acos(-1.0))

#define lowbit(x) (x&(-x))

#define mp make_pair

#define ls o<<1

#define rs o<<1 | 1

#define lson o<<1, l, mid

#define rson o<<1 | 1, mid+1, r

#define pii pair#pragma comment(linker, "/stack:16777216")

typedef long long ll;

typedef unsigned long long ull;

//typedef int ll;

using namespace std;

ll qpow(ll a, ll b)return res;}

ll powmod(ll a, ll b)return res;}

//head

struct edge

*h[maxn], *edges, e[maxm];

bool done[maxn];

int size[maxn];

int mx[maxn];

vectordis;

int n, root, ans, nsize;

void addedges(int u, int v, int w)

void init()

void read()

}void getroot(int u, int fa)

mx[u] = max(mx[u], nsize - size[u]);

if(mx[u] < mx[root]) root = u;

}void getdis(int u, int fa, int dist)

}int calc(int u, int dist)

return a * a + b * c * 2;

}void solve(int u)

}void work()

int main()

return 0;

}

bzoj2152 聰聰可可 點分治

點分治求路徑長度為3的倍數的鏈的條數,結果用分數表示。這道題明顯是樹形dp簡單,然而還是寫了點分治 練習所用沒辦法啊 ac 如下 include include include define n 50005 using namespace std int n,m,tot,sum,rt,ans,t 3...

BZOJ2152 聰聰可可 點分治

此題明顯可以點分治解決,對每層分治塊遞迴子塊,求出塊內有多少距離 3 0,1,2的節點,與之前其他塊的資訊歸併,即ans f 0 g 0 f 1 g 2 f 2 g 1 再把g加到f上面去即可 注意點分治求重心一定注意不要打錯字母 打混x,y之類的 注意此題題意詭異,點對要 2 n 單點也算,反過來...

BZOJ 2152 聰聰可可 樹形DP

給出一顆n個點帶邊權的樹 n 20000 求隨機選擇兩個點,使得它們之間的路徑邊權是3的倍數的概率是多少。首先總的對數是n n,那麼只需要統計路徑邊權是3的倍數的點對數量就行了。考慮將無根樹化為有根樹,令dp x i 表示以x點為路徑起點,x的某個子孫為路徑終點的邊權值模3為i的點對數量。那麼顯然有...