一棵 $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 longview code#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);}}
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...