bzoj 2159 Crash 的文明世界

2022-05-22 19:51:11 字數 1823 閱讀 3293

一棵 $n$ 個點的樹,給乙個 $k$,對於每個 $i$,求 $\sum\limits_^n dist(i,j)^k$,膜 10007

$n \leq 50000,k \leq 150$

sol:

用乙個斯特林數公式 $dist(i,j)^k = \sum\limits_^k \binom \times l! \times stirling2(k,l)$

於是要求的就是 $\sum\limits_^k stirling2(k,l) \times l! \times \sum\limits_^n \binom$

第二類斯特林數和階乘可以預處理,主要是要求 $\binom$

可以用組合數遞推公式 $\binom = \binom + \binom$

做乙個樹形 dp,$up_$ 表示除了 $i$ 子樹裡的點,二項式係數下面那個數為 $j$ ,對 $i$ 答案的貢獻,$dw_$ 表示 $i$ 子樹裡的點,二項式係數下面那個數為 $j$ ,對 $i$ 答案的貢獻

$dw_$ 很好轉移

$up_$ 就用它和它的父親容斥一下,注意根沒有父親

還有注意,這題模數是 $10007$,而 $n$ 是 $50000$,不把 $n$ 模一下就掛了

#include #define ll long long

#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)

#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)

using

namespace

std;

inline

intread()

const

int maxn = 50010, mod = 10007;//

inline void mo(int &x)

inline int inc(int x, int y)

inline

int dec(int x, int y)

inline

int mul(int x, int y)

intn, k;

int first[maxn], to[maxn << 1], nx[maxn << 1

], cnt;

int s[200][200], fac[200], dw[maxn][200], up[maxn][200

];inline

void add(int u, int

v) void dfs_down(int x, int

pre)

}}int

nmod;

void dfs_up(int x, int

pre)

}for(int i=first[x];i;i=nx[i]) if(to[i] !=pre) dfs_up(to[i], x);

}int

l, a, b, q, now;

intmain() s[

0][0] = fac[0] = 1

; rep(i,

1, k) rep(j, 1

, i)

rep(i,

1, k) fac[i] = mul(i, fac[i - 1

]); dfs_down(

1, 0); dfs_up(1, 0

); rep(i,

1, n)

printf(

"%d\n

", ans);}}

view code

BZOJ2159 Crash 的文明世界

這篇寫差分表和斯特林數介紹的不錯 這題就是要計算這個東西 s i j 1n dist i,j ks i j 1nd ist i,j k這個東西很難維護,我們把di st i j k d is t i,j k拆一下s u v kj 0d u,v d u,v j s u v j 0 kd u v d u...

bzoj 2159 Crash 的文明世界

又來做了一次。之前寫得實在是太差了,這次寫好點吧。這裡介紹用斯特林數展開的方法 如果不會的可以先看看這裡 我們知道xn k 0 ns n k k c x,k x n sum ns n,k k c x,k xn k 0n s n,k k c x k 因此,如果想知道答案,其實就是要知道對於每乙個k k...

BZOJ 2159 Crash 的文明世界

記得去年暑假集訓的時候本來想了乙個動態點分的做法的,然後寫道一半因為某些不知名原因就沒寫了,然後就一直放著,然後發現斯特林反演真nm好寫 首先考慮用關於冪的斯特林反演 m n sum m left times i times c m i 套上去就是 ans x sum n dis i,x k sum...