"JSOI2019" neural network (a combination of inclusion and exclusion + count + backpack dp)

Address

Luogu5333
Loj3102

Solution

Easy to find, on a Hamilton cycle essentially of: each tree is split into several pieces directional path, then all of the directed path to form a ring, two adjacent on the ring may not be from the same directional path a tree.

First find \ (g_ {i, j} \) represents the section \ (I \) tree is split into \ (J \) strip to have the number of program paths.

Consider \ (\ text {DP} \) , denoted \ (f_ {u, i, 0/1/2/3} \) respectively: \ (U \) subtree split into \ (I \) paths , \ (U \) is the path start point, the end of the path, the path to a single point, neither the path nor the number of the starting point of the end of the path program.

Note that \ (f_ {u, i, 0/1} \) allowed \ (U \) a single point to the path. Transfer to casually talk about. Final \ (G_ {I, J} = F_ {U, I, F_ {0} + U, I,. 1 + F_ {U}, I, F_ {2} + U, I,. 3} \) .

Next, assuming that all of us (\ i∈ [1, m]) \ , has determined that the first \ (i \) tree is split into \ (a_i \) strand] path, how to calculate the answer?

Consider inclusion and exclusion. Enumeration of \ (I \) path tree is divided into the ring up \ (B_i \) segments. We first Imperial \ (m \) tree \ (1 \) path where the number of nodes is a first ring path, the number of programs under this condition is:
\ [(\ prod_ {1} ^ = I mC_ {a_i-1} ^ { b_i-1}) × (\ prod_ {i = 1} ^ {m-1} g_ {i, a_i} × a_i!) × g_ {m, a_m} × (a_m-1 )! × \ frac {(\ sum_ {i = 1} ^ {m-1} b_i)!} {\ prod_ {i = 1} ^ {m-1} b_i!} × C _ {(\ sum_ {i = 1} ^ nb_i) -2} ^ {b_m-1} \] where \ (\ prod_ {i = 1 } ^ mC_ {a_i-1} ^ {b_i-1} \) represents the path of each tree into \ (I \) the number of program segments, \ (I G_ {,} × a_i a_i! \) represents the first \ (I \) selecting that tree \ (a_i \) paths form a number of programs are arranged.

If it is determined the selected path is formed which is arranged, divided into \ (B_i \) What are the segment, the problem is transformed into: a first \ (I \) colors balls have \ (B_i \) a, with there is no difference between the color balls, seeking all the requirements strung ring, so that the number of two adjacent different color scheme.

Imperial ring Imperial first path corresponds to a first color of the ball necessarily \ (m \) , a color of the ball is not the last \ (m \) , then the ring is broken chain. Therefore, before the first \ (m-1 \) colors good ball row (program number), and finally in the middle \ ((\ sum b_i) -2 \) selected positions in the \ (b_m-1 \) color discharge position \ (m \) balls, the remaining space to other ball can.

Together with the contribution of the answer after receiving i.e. repellent coefficients \ [(\ prod_ {i = 1} ^ mC_ {a_i-1} ^ {b_i-1}) × (-1) ^ {\ sum_ {i = 1} ^ ma_i-b_i} × (\ prod_ {i = 1} ^ {m-1} g_ {i, a_i} × a_i!) × g_ {m, a_m} × (a_m-1)! × \ frac {(\ sum_ {i = 1} ^ {m -1} b_i)!} {\ prod_ {i = 1} ^ {m-1} b_i!} × C _ {(\ sum_ {i = 1} ^ nb_i) -2} ^ {b_m-1} \]

But direct enumerate all \ (a_i, b_i \) complexity is exponential, consider optimizing.

- recording \ (I \) of the tree points to \ (cnt_i \) . For the first \ (I \) tree ( \ (i∈ [. 1,. 1-m] \) ), enumeration \ (= a_i J, K B_i = \) , a polynomial can be written like this:

\[\sum_{j=1}^{cnt_i}g_{i,j}×i!\sum_{k=1}^jC_{j-1}^{k-1}×(-1)^{j-k}×\frac{x^k}{k!}\]

We then put this \ (m-1 \) polynomial multiplication, then \ (x ^ k \) is multiplied by the coefficient \ (K! \) . Thus obtained \ (x ^ k \) coefficients \ (a_k \) is equivalent to: For the \ (i∈ [. 1,. 1-m] \) , enumerate all \ (a_i, b_i \) satisfies \ (\ sum_ } ^ = I. 1 {{} B_i. 1-m = K \) , then \ [(\ prod_ {i = 1} ^ mC_ {a_i-1} ^ {b_i-1}) × (-1) ^ { \ sum_ {i = 1} ^ ma_i-b_i} × (\ prod_ {i = 1} ^ {m-1} g_ {i, a_i} × a_i!) × \ frac {(\ sum_ {i = 1} ^ {m-1} b_i)! } {\ prod_ {i = 1} ^ {m-1} b_i!} \] included \ (a_k \) .

The next write of \ (m \) polynomial, denoted \ (b_k \) represents the first polynomial \ (K \) coefficients of terms:

\[\sum_{j=1}^{cnt_m}g_{m,j}×(j-1)!×\sum_{k=1}^jC_{j-1}^{k-1}×(-1)^{j-k}×x^k\]

Finally enumeration \ (K = \ sum_ = {I}. 1. 1} ^ {m-B_i \) , then enumeration \ (B_M J = \) , the \ (A_k × B_j × C_ { k + j-2} ^ {j-1} \) included in the answer to.

Time complexity \ (O ((\ SUM cnt_i) ^ 2) \) .

Code

#include <bits/stdc++.h>

using namespace std;

#define ll long long

template <class t>
inline void read(t & res)
{
    char ch;
    while (ch = getchar(), !isdigit(ch));
    res = ch ^ 48;
    while (ch = getchar(), isdigit(ch))
        res = res * 10 + (ch ^ 48);
}

const int e = 5005, o = 305, mod = 998244353;

int g[o][e], f[e][e][4], sze[e], m, n, ans, tmp[e][4], cnt, pre[e], h[e], p[o][e];
int adj[e], nxt[e << 1], go[e << 1], num, tot[o], fac[e], inv[e], a[o][e];

inline void add(int &x, int y)
{
    (x += y) >= mod && (x -= mod);
}

inline int plu(int x, int y)
{
    add(x, y);
    return x;
}

inline int mul(int x, int y)
{
    return (ll)x * y % mod;
}

inline int ksm(int x, int y)
{
    int res = 1;
    while (y)
    {
        if (y & 1) res = mul(res, x);
        y >>= 1;
        x = mul(x, x);
    }
    return res;
}

inline void link(int x, int y)
{
    nxt[++num] = adj[x]; adj[x] = num; go[num] = y;
    nxt[++num] = adj[y]; adj[y] = num; go[num] = x;
}

inline int c(int x, int y)
{
    if (x < y) return 0;
    if (x == y) return 1;
    return mul(fac[x], mul(inv[y], inv[x - y]));
}

inline void clear()
{
    int i, j, k; num = ans = 0;
    for (i = 1; i <= n; i++)
    {
        adj[i] = 0;
        for (j = 1; j <= n; j++)
            for (k = 0; k <= 3; k++)
                f[i][j][k] = 0;
    }
}

inline void dfs(int u, int pa)
{
    sze[u] = f[u][1][2] = 1;
    int i, j, k, l;
    for (i = adj[u]; i; i = nxt[i])
    {
        int v = go[i];
        if (v == pa) continue;
        dfs(v, u);
        for (j = 1; j <= sze[u] + sze[v]; j++)
            for (k = 0; k <= 3; k++)
                tmp[j][k] = f[u][j][k], f[u][j][k] = 0;
        for (j = 1; j <= sze[u]; j++)
            for (k = 1; k <= sze[v]; k++)
            {
                int s = plu(f[v][k][0], f[v][k][2]);
                add(f[u][j + k - 1][0], mul(tmp[j][2], s));
                add(f[u][j + k - 1][3], mul(tmp[j][1], s));
                
                s = plu(f[v][k][1], f[v][k][2]);
                add(f[u][j + k - 1][1], mul(tmp[j][2], s));
                add(f[u][j + k - 1][3], mul(tmp[j][0], s));
                
                s = 0;
                for (l = 0; l <= 3; l++)
                    add(s, f[v][k][l]);
                for (l = 0; l <= 3; l++)
                    add(f[u][j + k][l], mul(tmp[j][l], s));
            }
        sze[u] += sze[v];
    }
}

inline void solve(int k)
{
    read(n); clear();
    cnt += n; tot[k] = n; pre[k] = tot[k] + pre[k - 1];
    int i, x, y, j;
    for (i = 1; i < n; i++)
        read(x), read(y), link(x, y);
    dfs(1, 0);
    for (i = 1; i <= n; i++)
        for (j = 0; j <= 3; j++)
            add(g[k][i], f[1][i][j]);
}

int main()
{
    read(m);
    int i, j, k;
    for (i = 1; i <= m; i++)
        solve(i);
        
    fac[0] = 1;
    for (i = 1; i <= cnt; i++)
        fac[i] = mul(fac[i - 1], i);
    inv[cnt] = ksm(fac[cnt], mod - 2);
    for (i = cnt - 1; i >= 0; i--)
        inv[i] = mul(inv[i + 1], i + 1);
        
    for (i = 1; i < m; i++)
        for (j = 1; j <= tot[i]; j++)
            g[i][j] = mul(g[i][j], fac[j]);
        
    for (j = 1; j <= tot[m]; j++)
        g[m][j] = mul(g[m][j], fac[j - 1]);
        
    for (i = 1; i < m; i++)
        for (j = 1; j <= tot[i]; j++)
            for (k = 1; k <= j; k++)
            {
                int v = mul(g[i][j], c(j - 1, k - 1));
                v = mul(v, inv[k]);
                if ((j - k) & 1) add(p[i][k], mod - v);
                else add(p[i][k], v);
            }
    
    for (j = 1; j <= tot[m]; j++)
        for (k = 1; k <= j; k++)
        {
            int v = mul(g[m][j], c(j - 1, k - 1));
            if ((j - k) & 1) add(p[m][k], mod - v);
            else add(p[m][k], v);
        }
            
    a[0][0] = 1;
    for (i = 1; i < m; i++)
        for (j = 1; j <= pre[i]; j++)
            for (k = 1; k <= j && k <= tot[i]; k++)
                add(a[i][j], mul(a[i - 1][j - k], p[i][k]));
                
    for (i = 1; i <= pre[m - 1]; i++)
        for (j = 1; j <= tot[m]; j++)
        {
            int x = mul(a[m - 1][i], fac[i]), y = p[m][j];
            add(ans, mul(x, mul(y, c(i + j - 2, j - 1)))); 
        }
    cout << ans << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/cyf32768/p/12196010.html