[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)

Posted cnyali-tea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)相关的知识,希望对你有一定的参考价值。

技术图片

Solution:

? 由于
\[ x^m = \sum_i=0^m~m~\choose i~x~\brace ii! \]
? 将所求的式子化成这样,挖掘其性质,考虑是否能从儿子转移(或利用以求得信息)。
\[ \beginaligned S(u) &= \sum_i=1^ndis(u,i)^k\&= \sum_i=1^n\sum_j=0^kdis(u, i) \choose jk\brace jj!\&= \sum_j=0^kj!k\brace j\sum_i=1^ndis(u, i)\choose j \endaligned \]
? 由于组合数有:\(n\choose m = n - 1\choose m - 1 + n - 1\choose m\)

? 而从儿子及父亲到自己的距离为1,于是可以考虑换根树型dp求出每个点的 \(\sum_i=1^ndis(u, i)\choose j\)

? 设 \(f[u][j] = \sum_idis(u, i) \choose j\) 其中 \(i\)\(u\) 子树中的点。

? 设 \(g[u][j] = \sum_i=1^ndis(u, i)\choose j\)
\[ f[u][j] = \sum_v\in son(u)f[v][j] + f[v][j - 1]\g[u][j] = g[fa(u)][j-1]-f[u][j-2]-f[u][j-1]+g[fa(u)][j]-f[u][j-1]-f[u][j]+f[u][j] \]

Code

#include <vector>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long LL;
typedef unsigned long long uLL;

#define fir first
#define sec second
#define SZ(x) (int)x.size()
#define MP(x, y) std::make_pair(x, y)
#define PB(x) push_back(x)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n")
#define rep(i, a, b) for (register int i = (a), i##end = (b); (i) <= i##end; ++ (i))
#define drep(i, a, b) for (register int i = (a), i##end = (b); (i) >= i##end; -- (i))
#define REP(i, a, b) for (register int i = (a), i##end = (b); (i) < i##end; ++ (i))

inline int read() 
    register int x = 0; register int f = 1; register char c;
    while (!isdigit(c = getchar())) if (c == '-') f = -1;
    while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    return x * f;

template<class T> inline void write(T x) 
    static char stk[30]; static int top = 0;
    if (x < 0)  x = -x, putchar('-'); 
    while (stk[++top] = x % 10 xor 48, x /= 10, x);
    while (putchar(stk[top--]), top);

template<typename T> inline bool chkmin(T &a, T b)  return a > b ? a = b, 1 : 0; 
template<typename T> inline bool chkmax(T &a, T b)  return a < b ? a = b, 1 : 0; 

using namespace std;

const int maxN = 50004;
const int maxK = 153;
const int MOD = 10007;

int n, k;
int fac[maxK];
int stirl[maxK][maxK];
vector<int> ver[maxN];

void Input()

    n = read(), k = read();
    for (int i = 1; i < n; ++i)
    
        int u = read(), v = read();
        ver[u].push_back(v);
        ver[v].push_back(u);
    


void Init() 

    fac[0] = 1;
    rep (i, 1, k) 
        fac[i] = 1ll * fac[i - 1] * i % MOD;
    stirl[0][0] = stirl[1][1] = 1;
    rep (i, 2, k)
        rep (j, 1, i) 
            stirl[i][j] = (1ll * stirl[i - 1][j - 1] + 1ll * j * stirl[i - 1][j] % MOD) % MOD;


int f[maxN][maxK], g[maxN][maxK], tmp[maxK];

void dfs1(int u, int fa)

    f[u][0] = 1;
    for (int v : ver[u]) 
        if (v != fa)
        
            dfs1(v, u);
            f[u][0] = (1ll * f[u][0] + f[v][0]) % MOD;
            for (int j = 1; j <= k; ++j)
                f[u][j] = ((1ll * f[u][j] + f[v][j]) % MOD + f[v][j - 1]) % MOD;
        


void add(int &x, int y)

    x = (1ll * x + y + MOD) % MOD;


void dfs2(int u, int fa)

    if (!fa) 
        for (int i = 0; i <= k; ++i) g[u][i] = f[u][i];
    else 
    
        g[u][0] = g[fa][0];
        for (int j = 1; j <= k; ++j)
        
           int &x = g[u][j];
           x = 0;
           add(x, g[fa][j]);
           add(x, -f[u][j]);
           add(x, -f[u][j - 1]);
           add(x, g[fa][j - 1]);
           add(x, -f[u][j - 1]);
           add(x, f[u][j]);
           if (j >= 2) add(x, -f[u][j - 2]);
        
    
    for (int v : ver[u])
        if (v != fa)
            dfs2(v, u);



void Solve()

    dfs1(1, 0);
    dfs2(1, 0);
    for (int i = 1; i <= n; ++i)
    
        int ans = 0;
        for (int j = 0; j <= k; ++j)
            ans = (1ll * ans + 1ll * stirl[k][j] * fac[j] % MOD * g[i][j] % MOD) % MOD;
        cout << ans << endl;
    


int main() 

#ifndef ONLINE_JUDGE
    freopen("tmp.in", "r", stdin);
    freopen("tmp.out", "w", stdout);
#endif

    Input();

    Init();

    Solve();

    return 0;

以上是关于[LuoguP1829]Crash的文明表格(二次扫描与换根+第二类斯特林数)的主要内容,如果未能解决你的问题,请参考以下文章

P1829 [国家集训队]Crash的数字表格 / JZPTAB

「luogu1829」 [国家集训队]Crash的数字表格

P1829 [国家集训队]Crash的数字表格 / JZPTAB

bzoj 2159: Crash 的文明世界

BZOJ2159 : Crash 的文明世界

bzoj 2159: Crash 的文明世界