#csps1. csps1

csps1

一、单项选择题(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)

  1. 关于 CSP-S 第一轮常见的 GNU/Linux 编程环境与 C++ 语法,下列说法最合理的是(){{ select(1) }}
  • 只要程序包含 <bits/stdc++.h>,就一定可以在任意 ISO C++14 编译器上通过
  • -O2 会自动把所有未定义行为转化为运行时异常,便于调试
  • PBDS 的 tree 属于 GNU 扩展,常用于实现 order_of_keyfind_by_order;若程序使用结构化绑定等 C++17 语法,在默认 C++14 语义下可能无法通过编译
  • #define int long long 不会影响函数重载、数组空间和第三方库模板实例化,因此是完全安全的写法
  1. 阅读下面程序,输出正确的是(){{ select(2) }}
    #include <bits/stdc++.h>
    using namespace std;
    void f(int& x) { cout << "L"; x += 2; }
    void f(const int& x) { cout << "C"; }
    void f(int&& x) { cout << "R"; x += 20; }
    template <class T>
    void h(T&& x) {
        f(forward<T>(x));
    }
    int main() {
        int a = 5;
        auto&& r = (a);
        h(r);
        h(move(r));
        h(a + 1);
        f(r);
        cout << ":" << a << "\n";
        return 0;
    }
    
  • LRRL:27
  • LRRL:29
  • LCRL:29
  • 程序无法通过编译
  1. 阅读下面程序,输出为(){{ select(3) }}
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        unsigned int y = (1u << 31) >> 30;
        unsigned long long x = 0;
        for (int i = 0; i < 64; i += 21) x |= (1ULL << i);
        int z = 5 & 3 == 1;
        cout << ((x >> 42) & 7) << " " << y << " " << z << "\n";
        return 0;
    }
    
  • 1 2 0
  • 1 2 1
  • 3 2 0
  • 程序中 1ULL << 63 一定未定义,因此没有确定输出
  1. 阅读下面使用 PBDS 的程序,输出为(){{ select(4) }}
    #include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
    using namespace std;
    using namespace __gnu_pbds;
    typedef tree<pair<int,int>, null_type, less<pair<int,int> >,
                 rb_tree_tag, tree_order_statistics_node_update> ordered_set;
    int main() {
        ordered_set tr;
        tr.insert({5, 1});
        tr.insert({1, 2});
        tr.insert({5, 3});
        tr.insert({3, 4});
        tr.insert({5, 5});
        cout << tr.order_of_key({5, 4}) << " ";
        auto it = tr.find_by_order(2);
        cout << it->first << "," << it->second << " ";
        tr.erase({5, 3});
        cout << tr.order_of_key({5, 100}) << "\n";
        return 0;
    }
    
  • 3 5,3 3
  • 4 5,1 4
  • 4 5,3 4
  • 5 3,4 4
  1. 关于 C++ STL 容器的迭代器和引用失效规则,下列说法正确的是(){{ select(5) }}
  • vector 调用 erase(pos) 只会使指向被删元素的迭代器失效,之后元素的迭代器仍然有效
  • deque 在中间位置插入元素时,原有迭代器一定全部有效
  • list 进行一次合法的 splice 调用移动节点时,指向被移动元素的迭代器和引用仍然有效,只是元素所属容器可能改变
  • unordered_map 调用 rehash 后,原有迭代器一定仍然有效
  1. 某有向图缩点后得到 8 个强连通分量 A,B,C,D,E,F,G,H,边为:
    A -> C, B -> C, C -> D, D -> E, F -> D, E -> G, F -> H, H -> G
    
    若不添加其他边,则至少需要添加多少条有向边才能使原图强连通?若先额外添加一条从分量 G 指向分量 A 的边,再使原图强连通又至少需要多少条边?(){{ select(6) }}
  • 2, 1
  • 2, 2
  • 3, 2
  • 3, 1
  1. 二分图左部点为 1,2,3,4,5,6,右部点为 a,b,c,d,e,f,边为:
    1-a, 1-b, 2-a, 2-c, 3-b, 3-d, 4-c, 4-e, 5-d, 5-e, 5-f, 6-f
    
    关于该图,下列说法正确的是(){{ select(7) }}
  • 最大匹配数为 6,最小点覆盖大小为 6;若删去边 6-f,最大匹配数变为 5
  • 最大匹配数为 5,最小点覆盖大小为 6;若删去边 6-f,最大匹配数不变
  • 最大匹配数为 6,最小点覆盖大小为 5;若删去边 6-f,最大匹配数变为 4
  • 最大匹配数为 7,最小点覆盖大小为 7;若删去边 6-f,最大匹配数变为 6
  1. 长度为 10 的数组初始为:
    2, -1, 4, 0, 3, -2, 5, 1, -3, 2
    
    依次执行以下区间加法:
    [2,7] 加 3
    [5,10] 加 -4
    [1,4] 加 2
    
    若用支持区间加、区间查询的线段树维护,则操作结束后区间 [3,9] 的元素和与全局最大值分别为(){{ select(8) }}
  • 6, 9
  • 7, 9
  • 7, 8
  • 9, 7
  1. 长度为 10 的数组初始全为 0。使用树状数组维护差分,add_range(l,r,v) 等价于 add(l,v)add(r+1,-v),其中 add(i,v) 依次访问 i, i+lowbit(i), ...,直到下标大于 10。执行:
    add_range(3, 8, 2)
    add_range(1, 4, 1)
    add_range(6, 10, -3)
    
    query(4) + query(7) 的值,以及 6 次内部 add 累计访问的树状数组下标次数分别为(){{ select(9) }}
  • 3, 12
  • 2, 12
  • 2, 14
  • 5, 14
  1. 对下列有向带权图从 1 号点运行标准堆优化 Dijkstra,不在第一次弹出终点时提前结束,而是直到堆空为止。若每次弹出 (d,u) 时发现 d != dist[u] 就记作一个过期状态,则 dist[5] 与过期状态个数分别为(){{ select(10) }}
    1 -> 2 (8), 1 -> 3 (3), 1 -> 5 (20)
    3 -> 2 (2), 3 -> 4 (7)
    2 -> 4 (2), 2 -> 5 (10)
    4 -> 5 (1)
    
  • 8, 0
  • 7, 3
  • 8, 3
  • 8, 4
  1. 长度为 12 的 01 串中,恰有 5 个字符为 1,且不含连续子串 010 的串共有()个{{ select(11) }}
  • 120
  • 126
  • 132
  • 140
  1. 某随机过程从状态 0 开始。每一步独立地以概率 1/2 使状态加 1,以概率 1/2 使状态变回 0;当状态第一次达到 3 时停止。停止前的期望步数为(){{ select(12) }}
  • 14
  • 12
  • 10
  • 8
  1. 有一个 34 列的棋盘。每一行可以选择若干个格子,但同一行中相邻两列不能同时被选;同一列最多只能在一行中被选。问四列都恰好被选中一次的方案数,以及所有合法选择方案数分别为(){{ select(13) }}
  • 24, 128
  • 20, 142
  • 24, 142
  • 32, 156
  1. 一棵树有 9 个点,边为:
    1-2, 1-3, 1-4, 2-5, 2-6, 3-7, 4-8, 4-9
    
    点权依次为:
    w1=6, w2=10, w3=7, w4=8, w5=5, w6=9, w7=4, w8=11, w9=3
    
    在相邻点不能同时选择的限制下,最大点权和是多少?若强制 1 号点不选,最大点权和又是多少?(){{ select(14) }}
  • 38, 35
  • 37, 35
  • 38, 34
  • 36, 35
  1. 设组合数 C(n,k)=n!/(k!(n-k)!)。根据 Lucas 定理,C(2026,1024) mod 13 的值为(){{ select(15) }}
  • 0
  • 12
  • 6
  • 11

二、阅读程序(程序输入不超过数组或字符串定义的范围;判断题正确填对,错误填错;除特殊说明外,判断题1.5分,选择题3分,标注4分题为4分,共计40分)

(1)

#include <bits/stdc++.h>
using namespace std;
const int HM = 1009;
const int BASE = 17;
int main() {
    int n, L, R;
    cin >> n >> L >> R;
    vector<int> a(n + 1);
    vector<long long> s(n + 1);
    vector<int> pw(n + 1, 1), hs(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
        int x = ((a[i] % 10) + 10) % 10;
        hs[i] = (hs[i - 1] * BASE + x) % HM;
        pw[i] = 1LL * pw[i - 1] * BASE % HM;
    }
    deque<int> q;
    int ptr = 0;
    long long best = -(1LL << 60);
    int ways = 0, bl = 0, br = 0, code = 0;
    for (int r = 1; r <= n; ++r) {
        while (ptr <= r - L) {
            while (!q.empty() && s[q.back()] >= s[ptr]) q.pop_back();
            q.push_back(ptr++);
        }
        while (!q.empty() && q.front() < r - R) q.pop_front();
        if (q.empty()) continue;
        int p = q.front();
        long long cur = s[r] - s[p];
        int sub = (hs[r] - 1LL * hs[p] * pw[r - p]) % HM;
        if (sub < 0) sub += HM;
        if (cur > best) {
            best = cur;
            ways = 1;
            bl = p + 1;
            br = r;
            code = sub;
        } else if (cur == best) {
            ++ways;
            code += sub;
            if (code >= HM) code -= HM;
        }
    }
    cout << best << " " << ways << "\n";
    cout << bl << " " << br << " " << code << "\n";
    return 0;
}

给定输入:

9 2 4
3 -2 4 -1 -3 5 -2 2 1
  1. 队列 q 中保存的是候选前缀下标;在任意时刻,队列中的下标递增,且对应前缀和严格递增。(){{ select(16) }}
  1. 对给定输入,当循环处理到 r=6 并完成两次 while 后,队首下标为 2,此时 cur=5。(){{ select(17) }}
  1. 若删除 if (sub < 0) sub += HM;,由于 C++ 的 % 会自动返回非负余数,所有 sub 仍一定在 [0, HM) 内。(2分)(){{ select(18) }}
  1. 对给定输入,程序输出为(){{ select(19) }}
  • 6 1
    6 9 678
    
  • 6 3
    1 3 747
    
  • 5 3
    1 3 179
    
  • 7 1
    6 9 678
    
  1. 若仅将维护队尾的条件 s[q.back()] >= s[ptr] 改为 s[q.back()] > s[ptr],下列说法最合理的是(){{ select(20) }}
  • 最大区间和一定变大,因为保留了更多候选
  • 最大区间和不变,但相同前缀和时代表区间和哈希可能变化
  • 程序时间复杂度会从线性变成平方
  • 改动后队列下标不再递增
  1. 对给定输入,所有长度在 [L,R] 内且区间和等于 5 的区间共有()个{{ select(21) }}
  • 1
  • 2
  • 3
  • 4

(2)

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 105;
vector<int> g[MAXN], dag[MAXN], ug[MAXN];
int dfn[MAXN], low[MAXN], bel[MAXN], sz[MAXN], indeg[MAXN];
bool inst[MAXN];
vector<int> st;
int timer = 0, scc = 0;
void tarjan(int u) {
    dfn[u] = low[u] = ++timer;
    st.push_back(u);
    inst[u] = true;
    for (int v : g[u]) {
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if (inst[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (low[u] == dfn[u]) {
        ++scc;
        while (true) {
            int x = st.back();
            st.pop_back();
            inst[x] = false;
            bel[x] = scc;
            ++sz[scc];
            if (x == u) break;
        }
    }
}
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
    }
    for (int i = 1; i <= n; ++i)
        if (!dfn[i]) tarjan(i);
    set<pair<int,int> > seen;
    for (int u = 1; u <= n; ++u) {
        for (int v : g[u]) {
            int a = bel[u], b = bel[v];
            if (a == b) continue;
            if (seen.insert({a, b}).second) {
                dag[a].push_back(b);
                ug[a].push_back(b);
                ug[b].push_back(a);
                ++indeg[b];
            }
        }
    }
    queue<int> q;
    vector<int> topo;
    vector<int> dp(scc + 1);
    for (int i = 1; i <= scc; ++i) {
        dp[i] = sz[i];
        if (indeg[i] == 0) q.push(i);
    }
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        topo.push_back(u);
        for (int v : dag[u]) {
            dp[v] = max(dp[v], dp[u] + sz[v]);
            if (--indeg[v] == 0) q.push(v);
        }
    }
    bool bip = true;
    vector<int> col(scc + 1, -1);
    for (int i = 1; i <= scc; ++i) if (col[i] == -1) {
        col[i] = 0;
        queue<int> qq;
        qq.push(i);
        while (!qq.empty()) {
            int u = qq.front();
            qq.pop();
            for (int v : ug[u]) {
                if (col[v] == -1) {
                    col[v] = col[u] ^ 1;
                    qq.push(v);
                } else if (col[v] == col[u]) {
                    bip = false;
                }
            }
        }
    }
    int edges = (int)seen.size();
    int longest = 0;
    for (int x : dp) longest = max(longest, x);
    int code = 0;
    for (int u : topo) code = (code * 911 + u * 17 + sz[u]) % 1000003;
    cout << scc << " " << edges << " " << topo.size() << "\n";
    cout << longest << " " << (bip ? "BIP" : "ODD") << " " << code << "\n";
    return 0;
}

给定输入:

9 13
1 2
2 3
3 1
3 4
4 5
5 4
5 6
6 9
2 7
7 8
8 7
8 6
4 7
  1. 对给定输入,缩点编号从 1 到 5 对应的原点集合依次为 {9}{6}{7,8}{4,5}{1,2,3}。(){{ select(22) }}
  1. seen 的作用是去除压缩图中的重边,否则同一条压缩边可能使入度被重复累加。(){{ select(23) }}
  1. 若把 else if (inst[v]) low[u] = min(low[u], dfn[v]); 改成对所有已经访问过的 v 都执行 low[u] = min(low[u], dfn[v]);,Tarjan 缩点结果仍一定正确。(2分)(){{ select(24) }}
  1. 对给定输入,程序输出为(){{ select(25) }}
  • 5 6 5
    9 ODD 315756
    
  • 5 6 4
    9 BIP 315756
    
  • 4 6 4
    8 ODD 68893
    
  • 5 5 5
    7 BIP 315756
    
  1. 若仅删去输入中的最后一条边 4 7,程序输出变为(){{ select(26) }}
  • 5 6 5
    7 ODD 315756
    
  • 5 5 5
    7 BIP 315756
    
  • 4 5 4
    9 BIP 91386
    
  • 5 5 4
    7 ODD 315756
    
  1. 对给定输入,Kahn 拓扑过程中弹出的压缩点编号序列为(){{ select(27) }}
  • 5,4,3,2,1
  • 1,2,3,4,5
  • 5,3,4,2,1
  • 4,5,3,2,1

(3)

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 998244353;
long long mod_pow(long long a, long long b) {
    long long r = 1;
    while (b) {
        if (b & 1) r = r * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return r;
}
int main() {
    int n, m, T;
    cin >> n >> m >> T;
    vector<int> ban(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < m; ++j)
            if (s[j] == '#') ban[i] |= (1 << j);
    }
    vector<int> states, bits;
    for (int mask = 0; mask < (1 << m); ++mask) {
        if ((mask & (mask << 1)) == 0) {
            states.push_back(mask);
            bits.push_back(__builtin_popcount((unsigned)mask));
        }
    }
    int S = states.size();
    int maxK = n * m;
    vector<vector<long long> > dp(S, vector<long long>(maxK + 1, 0));
    int zero = find(states.begin(), states.end(), 0) - states.begin();
    dp[zero][0] = 1;
    for (int row = 1; row <= n; ++row) {
        vector<vector<long long> > ndp(S, vector<long long>(maxK + 1, 0));
        for (int id = 0; id < S; ++id) {
            int mask = states[id];
            if (mask & ban[row]) continue;
            int c = bits[id];
            for (int pid = 0; pid < S; ++pid) {
                int pre = states[pid];
                if ((mask & pre) || (mask & (pre << 1)) || (mask & (pre >> 1))) continue;
                for (int k = 0; k + c <= maxK; ++k) {
                    ndp[id][k + c] = (ndp[id][k + c] + dp[pid][k]) % MOD;
                }
            }
        }
        dp.swap(ndp);
    }
    vector<long long> ways(maxK + 1, 0);
    for (int id = 0; id < S; ++id)
        for (int k = 0; k <= maxK; ++k)
            ways[k] = (ways[k] + dp[id][k]) % MOD;
    vector<vector<long long> > C(maxK + 1, vector<long long>(maxK + 1, 0));
    for (int i = 0; i <= maxK; ++i) {
        C[i][0] = C[i][i] = 1;
        for (int j = 1; j < i; ++j)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
    }
    long long total = 0, weighted = 0, pairs = 0;
    for (int k = 0; k <= maxK; ++k) {
        total = (total + ways[k]) % MOD;
        weighted = (weighted + 1LL * k * ways[k]) % MOD;
        if (k >= 2) pairs = (pairs + C[k][2] * ways[k]) % MOD;
    }
    long long expect = weighted * mod_pow(total, MOD - 2) % MOD;
    cout << total << " " << ways[T] << "\n";
    cout << expect << " " << pairs << "\n";
    return 0;
}

给定输入:

3 4 3
....
.#..
....
  1. m=4 时,states 中共有 8 个状态。(){{ select(28) }}
  1. 条件 (mask & (pre << 1))(mask & (pre >> 1)) 会禁止相邻两行中斜向相邻的两个位置同时被选。(){{ select(29) }}
  1. 程序第二行输出的第一个数是普通十进制小数形式的数学期望。(2分)(){{ select(30) }}
  1. 对给定输入,程序输出为(){{ select(31) }}
  • 88 33
    294935834 187
    
  • 88 34
    107/44 187
    
  • 93 34
    294935834 214
    
  • 82 30
    214 187
    
  1. 若把给定输入第二行棋盘也改为 ....,即没有障碍,且仍令 T=3,则 totalways[T] 分别为(4分){{ select(32) }}
  • 88, 33
  • 93, 33
  • 93, 34
  • 96, 37

三、完善程序(单选题,每小题 3 分,共计 30 分)

(1)(区间唯一数统计)

给定长度为 n 的数组和 q 次询问。每次询问给出区间 [l,r],要求输出该区间中"恰好出现一次"的不同数的个数。下面程序将询问按右端点离线排序,并用树状数组维护每个可能左端点的贡献。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
struct Query {
    int l, r, id;
};
int n, q;
int a[MAXN], last[MAXN], pre[MAXN], bit[MAXN], ans[MAXN];
vector<int> disc;
vector<Query> query;
int lowbit(int x) {
    return x & -x;
}
void add(int x, int v) {
    for (int i = x; i <= n; i += lowbit(i)) {
        bit[i] += v;
    }
}
void range_add(int l, int r, int v) {
    if (____(1)____) return;
    add(l, v);
    ____(2)____;
}
int point_sum(int x) {
    int res = 0;
    for (int i = x; i > 0; i -= lowbit(i)) {
        res += bit[i];
    }
    return res;
}
void insert_pos(int pos) {
    int x = a[pos];
    if (last[x]) {
        ____(3)____;
    }
    ____(4)____;
    pre[x] = last[x];
    last[x] = pos;
}
bool cmp_query(const Query& A, const Query& B) {
    return ____(5)____;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> q;
    disc.reserve(n);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        disc.push_back(a[i]);
    }
    sort(disc.begin(), disc.end());
    disc.erase(unique(disc.begin(), disc.end()), disc.end());
    for (int i = 1; i <= n; ++i) {
        a[i] = lower_bound(disc.begin(), disc.end(), a[i]) - disc.begin() + 1;
    }
    query.resize(q);
    for (int i = 0; i < q; ++i) {
        cin >> query[i].l >> query[i].r;
        query[i].id = i;
    }
    sort(query.begin(), query.end(), cmp_query);
    int cur = 0;
    for (const Query& qu : query) {
        while (cur < qu.r) insert_pos(++cur);
        ans[qu.id] = point_sum(qu.l);
    }
    for (int i = 0; i < q; ++i) {
        cout << ans[i] << "\n";
    }
    return 0;
}
  1. ① 处应填(){{ select(33) }}
  • l > r
  • l == r
  • l < r
  • l + 1 > r
  1. ② 处应填(){{ select(34) }}
  • add(r, -v)
  • add(l + 1, -v)
  • add(r + 1, v)
  • add(r + 1, -v)
  1. ③ 处应填(){{ select(35) }}
  • range_add(last[x] + 1, pos, -1)
  • range_add(pre[x] + 1, last[x], -1)
  • range_add(pre[x], last[x] - 1, -1)
  • range_add(pre[x] + 1, pos, -1)
  1. ④ 处应填(){{ select(36) }}
  • range_add(pre[x] + 1, last[x], 1)
  • range_add(1, pos, 1)
  • range_add(last[x] + 1, pos, 1)
  • range_add(pos + 1, n, 1)
  1. ⑤ 处应填(){{ select(37) }}
  • A.r < B.r
  • A.l < B.l
  • A.id < B.id
  • A.r > B.r

(2)(树上限额独立集计数)

给定一棵 n 个点的树,求选出恰好 K 个点且任意相邻两点不同时被选的方案数,答案对 1000000007 取模。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 205;
const long long MOD = 1000000007LL;
int n, K, sz[MAXN];
vector<int> g[MAXN];
long long dp[MAXN][2][MAXN], tmp[2][MAXN];
void dfs(int u, int fa) {
    sz[u] = 1;
    ____(6)____;
    for (int v : g[u]) {
        if (v == fa) continue;
        dfs(v, u);
        memset(tmp, 0, sizeof(tmp));
        for (int i = 0; i <= min(sz[u], K); ++i) {
            for (int j = 0; j <= min(sz[v], K - i); ++j) {
                ____(7)____;
                ____(8)____;
            }
        }
        ____(9)____;
        for (int t = 0; t <= min(sz[u], K); ++t) {
            dp[u][0][t] = tmp[0][t];
            dp[u][1][t] = tmp[1][t];
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> K;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1, 0);
    cout << ____(10)____ << "\n";
    return 0;
}
  1. ⑥ 处应填(){{ select(38) }}
  • dp[u][0][0] = 1; if (K >= 1) dp[u][1][1] = 1
  • dp[u][0][1] = 1; dp[u][1][0] = 1
  • dp[u][0][0] = dp[u][1][0] = 1
  • dp[u][0][1] = dp[u][1][1] = 1
  1. ⑦ 处应填(){{ select(39) }}
  • tmp[0][i + j] = (tmp[0][i + j] + dp[u][0][i] * dp[v][0][j]) % MOD
  • tmp[0][i + j] = (tmp[0][i + j] + dp[u][1][i] * (dp[v][0][j] + dp[v][1][j])) % MOD
  • tmp[0][i + j] = (tmp[0][i + j] + dp[u][0][i] * dp[v][1][j]) % MOD
  • tmp[0][i + j] = (tmp[0][i + j] + dp[u][0][i] * ((dp[v][0][j] + dp[v][1][j]) % MOD)) % MOD
  1. ⑧ 处应填(){{ select(40) }}
  • tmp[1][i + j] = (tmp[1][i + j] + dp[u][1][i] * ((dp[v][0][j] + dp[v][1][j]) % MOD)) % MOD
  • tmp[1][i + j] = (tmp[1][i + j] + dp[u][1][i] * dp[v][0][j]) % MOD
  • tmp[1][i + j] = (tmp[1][i + j] + dp[u][0][i] * dp[v][0][j]) % MOD
  • tmp[1][i + j] = (tmp[1][i + j] + dp[u][1][i] * dp[v][1][j]) % MOD
  1. ⑨ 处应填(){{ select(41) }}
  • sz[v] += sz[u]
  • sz[u] += sz[v]
  • sz[u] = max(sz[u], sz[v])
  • ++sz[u]
  1. ⑩ 处应填(){{ select(42) }}
  • (dp[1][0][K] + dp[1][1][K]) % MOD
  • dp[1][1][K]
  • dp[1][0][K]
  • (dp[1][0][K] * dp[1][1][K]) % MOD