zoukankan      html  css  js  c++  java
  • 「十二省联考 2019」希望

    「十二省联考 2019」希望

    下面全是口胡

    传送门

    Loj

    题解

    暴力

    首先考虑一个暴力的(dp),设(f_{u,i})表示以(u)为根的子树,最长的长度不超过(j)的连通块个数,(g_{u,i})表示(u)子树外的长度不超过(i)的连通块个数.这个时候有:

    [f_{u,i}=prod_{vin son_u}(f_{v,i-1}+1) \ g_{u,i}=g_{fa,i-1}prod_{v in son_{fa},v e u}f_{v,i-2}+1 ]

    然后答案考虑容斥,如果你对于每一个(u)计算(f_{u,L}*g_{u,L}),会算重复一些连通块,那么根据如下事实:

    连通块的交还是一个连通块,我们可以想到一个容斥,即:点的贡献-边的贡献就是答案.

    所以答案为:((f_{u,L}*g_{u,L})^k-(f_{u,L-1}*(g_{u,L}-1))^k)

    优化

    接下来考虑怎么优化这个求(f)(g)的过程.

    (f_{u,i} ightarrow f_{u,i}+1),那么这就是一个长链剖分转移(dp),然后打一个全局标记.

    但是这个时候不会转移(len_v)以后的数字,这个时候要给全局打一个乘法标记,然后对前面打一个逆元的乘法.

    计算(g)你需要考虑暴力计算下,我们可以通过前后缀积计算.

    长链剖分下,我们还是可以计算前缀积,后缀积考虑用一个回退数据结构维护即可.

    代码

    把儿子的代码贴过来

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <list>
    #include <algorithm>
    #define ll long long
    #define Add(a, b) (a + b + Mod) % Mod
    #define Mul(a, b) 1ll * a *b % Mod
    #define Assign(x) 
        (f[x] = pf, pf += T.len[x] + 2, pg += T.len[x] + 2, g[x] = pg - max(L - T.len[x], 0), pg += T.len[x] + 2)
    #define Gmin(x, y) (x > (y) && (x = (y)))
    using namespace std;
    
    inline int read() {
        int sum = 0, f = 1;
        char c = getchar();
        while (c > '9' || c < '0') {
            if (c == '-')
                f = -1;
            c = getchar();
        }
        while (c <= '9' && c >= '0') {
            sum = sum * 10 + c - '0';
            c = getchar();
        }
        return f * sum;
    }
    
    const int N = 1000005;
    const int Mod = 998244353;
    struct edge {
        int to, next;
    } e[N << 1];
    int n, L, K, ans;
    int head[N], cnt;
    int _f[N << 4], _g[N << 4], *f[N], *g[N], *pf = _f, *pg = _g;
    
    inline void add(int x, int y) {
        e[++cnt] = (edge){ head[x], y };
        head[x] = cnt;
    }
    
    inline ll fpow(ll a, ll b) {
        ll ret = 1;
        while (b) {
            if (b & 1)
                ret = Mul(ret, a);
            a = Mul(a, a);
            b >>= 1;
        }
        return ret;
    }
    
    struct pre {
        int s[N], len[N], u[N], w[N], inv[N];
        vector<int> B[N], S[N];
        inline void dfs(int x, int fa) {
            inv[x] = 1;
            for (int i = head[x]; i; i = e[i].to) {
                int k = e[i].next;
                if (k == fa)
                    continue;
                dfs(k, x);
                if (len[k] > len[s[x]])
                    s[x] = k;
                inv[x] = Mul(inv[x], inv[k]);
            }
            len[x] = len[s[x]] + 1;
            inv[x] = Add(inv[x], 1);
            if (!s[x])
                return;
            int maxn = 0;
            for (int i = head[x]; i; i = e[i].to) {
                int k = e[i].next;
                if (k == fa || k == s[x])
                    continue;
                B[len[k]].push_back(k);
                maxn = max(maxn, len[k]);
            }
            for (int i = maxn; i >= 0; i--) {
                for (int j = 0, mx = B[i].size(); j < mx; j++) S[x].push_back(B[i][j]);
                B[i].clear();
            }
        }
        inline void init() {
            int tot = 0;
            len[0] = -1;
            dfs(1, 0);
            w[0] = 1;
            for (int i = 1; i <= n; i++)
                if (inv[i])
                    u[++tot] = i, w[tot] = Mul(w[tot - 1], inv[i]);
            w[tot] = fpow(w[tot], Mod - 2);
            for (int i = tot; i; i--) {
                int x = inv[u[i]];
                inv[u[i]] = Mul(w[i], w[i - 1]);
                w[i - 1] = Mul(w[i], x);
            }
        }
    } T;
    
    struct back {
        struct pr {
            int *w, v;
        };
        list<pr> t;
        inline void ins(int &x) { t.push_back((pr){ &x, x }); }
        inline void reset() {
            while (!t.empty()) *(t.back().w) = t.back().v, t.pop_back();
        }
    } S[N];
    
    struct fff {
        int mul[N], imul[N], add[N], lim[N], zero[N];
        inline int gv(int x, int p) {
            return Gmin(p, T.len[x]), Add(1LL * mul[x] * (p < lim[x] ? f[x][p] : zero[x]) % Mod, add[x]);
        }
        inline int giv(int x, int v) { return Mul(imul[x], Add(v, -add[x])); }
        inline void dfs(int x, int fa) {
            int ls = T.s[x];
            if (!ls) {
                lim[x] = mul[x] = imul[x] = add[x] = 1;
                //	add[x]=Add(add[x],1);//return ;
                goto End;
            }
            f[T.s[x]] = f[x] + 1;
            dfs(T.s[x], x);
            mul[x] = mul[T.s[x]];
            imul[x] = imul[T.s[x]];
            add[x] = add[T.s[x]];
            zero[x] = zero[T.s[x]];
            lim[x] = lim[T.s[x]] + 1;
            f[x][0] = giv(x, 1);
            for (int i = 0, mx = T.S[x].size(); i < mx; i++) {
                int k = T.S[x][i];
                ls = k;
                Assign(k);
                dfs(k, x);
                for (int j = 0; j <= T.len[k] + 1; j++) {
                    if (lim[x] == j)
                        S[k].ins(lim[x]), S[k].ins(f[x][j]), f[x][lim[x]++] = zero[x];
                    S[k].ins(f[x][j]);
                    f[x][j] = giv(x, Mul(gv(x, j), (j ? gv(k, j - 1) : 1)));
                }
                if (T.len[x] <= T.len[k] + 1)
                    continue;
                int w = gv(k, T.len[k]);
                if (!w)
                    S[k].ins(lim[x]), S[k].ins(zero[x]), lim[x] = T.len[k] + 1, zero[x] = giv(x, 0);
                else {
                    S[k].ins(mul[x]);
                    S[k].ins(imul[x]);
                    S[k].ins(add[x]);
                    mul[x] = Mul(mul[x], w);
                    add[x] = Mul(add[x], w);
                    imul[x] = Mul(imul[x], T.inv[k]);
                    for (int j = 0; j <= T.len[k] + 1; j++)
                        S[k].ins(f[x][j]), f[x][j] = giv(x, Mul(gv(x, j), T.inv[k]));
                }
            }
            S[ls].ins(add[x]);
        End:
            add[x] = Add(add[x], 1);
        }
        inline void solve() {
            Assign(1);
            dfs(1, 0);
        }
    } F;
    
    struct ggg {
        int mul[N], imul[N], zero[N], add[N], lim[N], u[N];
        //	inline int GV(CI x,CI p) {return XSum(1LL*Mul[x]*(p<Lim[x]?g[x][p]:Zero[x])%X,Add[x]);}//与之前类似
        inline int gv(int x, int p) { return Add(Mul(mul[x], (p < lim[x] ? g[x][p] : zero[x])), add[x]); }
        inline int giv(int x, int v) { return Mul(imul[x], Add(v, -add[x])); }
        inline void dfs(int x, int fa) {
            //		for(int i=0;i<=T.len[x];i++) printf("g[%d][%d]=%d
    ",x,i,g[x][i]);
            u[0] = 1;
            reverse(T.S[x].begin(), T.S[x].end());
            ans = Add(ans, fpow(Mul(Add(F.gv(x, L), -1), gv(x, L)), K));
            if (fa)
                ans = Add(ans, -fpow(Mul(Add(F.gv(x, L - 1), -1), Add(gv(x, L), -1)), K));
            if (!T.s[x])
                return;
            int prod = 1, Mx = 0;
            for (int i = 0, mx = T.S[x].size(); i < mx; i++) {
                int k = T.S[x][i];
                S[k].reset();
                lim[k] = L + 1;
                mul[k] = imul[k] = 1;
                for (int j = max(L - T.len[k], 0); j <= L; j++) {
                    g[k][j] = Add(Mul((j ? gv(x, j - 1) : 0),
                                      (j > 1 ? Mul(F.gv(x, j - 1), (j - 2 > Mx ? prod : u[j - 2])) : 1)),
                                  1);
                }
                for (int j = 0; j <= T.len[k]; j++) u[j] = Mul((j > Mx ? prod : u[j]), F.gv(k, j));
                prod = Mul(prod, F.gv(k, Mx = T.len[k]));
            }
            int ls = T.s[x];
            g[T.s[x]] = g[x] - 1;
            mul[T.s[x]] = mul[x];
            imul[T.s[x]] = imul[x];
            add[T.s[x]] = add[x];
            zero[T.s[x]] = zero[x];
            lim[T.s[x]] = lim[x] + 1;
            if (L <= T.len[T.s[x]])
                g[T.s[x]][0] = giv(T.s[x], 0);
            for (int i = 0, mx = T.S[x].size(); i < mx; i++) {
                int k = T.S[x][i];
                for (int j = max(0, L - T.len[ls]); j <= min(L, T.len[k] + 2); j++) {
                    if (lim[ls] == j)
                        g[ls][lim[ls]++] = zero[ls];
                    g[ls][j] = giv(ls, Mul(gv(ls, j), (j > 1 ? F.gv(k, j - 2) : 1)));
                }
                if (L <= T.len[k] + 2)
                    continue;
                int w = F.gv(k, T.len[k]);
                if (!w)
                    lim[ls] = T.len[k] + 2, zero[ls] = giv(ls, 0);
                else {
                    mul[ls] = Mul(mul[ls], w);
                    add[ls] = Mul(add[ls], w);
                    imul[ls] = Mul(imul[ls], T.inv[k]);
                    for (int j = max(0, L - T.len[ls]); j <= min(L, T.len[k] + 2); j++) {
                        g[ls][j] = giv(ls, Mul(gv(ls, j), T.inv[k]));
                    }
                }
            }
            add[T.s[x]] = Add(add[T.s[x]], 1);
            dfs(T.s[x], x);
            for (int i = 0, mx = T.S[x].size(); i < mx; i++) {
                int k = T.S[x][i];
                if (k != fa)
                    dfs(k, x);
            }
        }
        inline void solve() {
            mul[1] = add[1] = imul[1] = 1;
            lim[1] = L + 1;
            dfs(1, 0);
        }
    
    } G;
    
    signed main() {
        //	freopen(".in","r",stdin);
        //  freopen(".out","w",stdout);
        n = read();
        L = read();
        K = read();
        for (int i = 1; i ^ n; i++) {
            int x = read(), y = read();
            add(x, y);
            add(y, x);
        }
        T.init();
        F.solve();
        G.solve();
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    [算法] Tarjan算法求割点
    [题解] POJ2689 [质数距离]
    [题解] 「NOIP2009」最优贸易
    pyCharm更换主题、字体大小和编辑器字体颜色
    python之冒泡排序简单算法
    修改pip阿里镜像
    Postman工具简介
    接口文档解析
    HTTP接口请求
    接口(API)测试学习
  • 原文地址:https://www.cnblogs.com/fexuile/p/13027067.html
Copyright © 2011-2022 走看看