zoukankan      html  css  js  c++  java
  • 【题录】ICPC2020 南京站、济南站

    南京站:

    J.

    操作:区间取max;查询:区间的石堆 + 一堆给定数目 (x) 的石堆所构成的 nim 游戏使先手必胜的先手操作个数(先手第一步的操作方案数)。

    由组合游戏的结论有若区间石子的异或和 ^ x 不为 0 则先手必胜,令这个总的异或和为 S。考虑一个石堆,如果先手最开始拿走这个石堆内的石子能够使得异或和 S' 为 0,已知只有一种拿走的操作方式。所以问题只需要考虑一开始动第 k 堆石子能否先手必胜,若能则答案 + 1。除去第 k 堆石子的其余石堆的石子数异或和为 S ^ a[k], 当且仅当 S ^ a[k] < a[k] 的时候 a[k] 可以经过操作变成 S ^ a[k],而当且仅当在 S 的二进制表示中最高位的 1 的位置上,a[k] 也为 1 该条件成立。

    因此使用吉司机线段树维护区间取 max 的操作,维护区间异或和以及每一个二进制位上为 1 的区间内数的个数。

    #include <bits/stdc++.h>
    using namespace std;
    #define BITS 32
    #define maxn 1000000
    #define INF 1500000000
    int n, q, a[maxn], minx[maxn], sminx[maxn], minnum[maxn], num[maxn][BITS];
    int mark[maxn], sum[maxn], bits[BITS];
    
    int read() {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void Push_Up(int p, int l, int r) {
        int ls = p << 1, rs = p << 1 | 1;
        if(minx[ls] == minx[rs]) {
            minx[p] = minx[ls], minnum[p] = minnum[ls] + minnum[rs];
            sminx[p] = min(sminx[ls], sminx[rs]);
        }
        else {
            if(minx[rs] < minx[ls]) swap(ls, rs);
            minx[p] = minx[ls], minnum[p] = minnum[ls];
            sminx[p] = min(sminx[ls], minx[rs]);
        }
        for(int K = BITS - 1; K >= 0; K --)
            num[p][K] = num[ls][K] + num[rs][K];
        sum[p] = sum[ls] ^ sum[rs];
    }
    
    void Work(int p, int l, int r, int x) {
        if(minx[p] >= x) return;
        for(int K = BITS - 1; K >= 0; K --) {
            if(minx[p] & bits[K]) num[p][K] -= minnum[p];
            if(x & bits[K]) num[p][K] += minnum[p];
        }
        if(minnum[p] & 1) sum[p] ^= minx[p] ^ x;
        minx[p] = x; 
        mark[p] = x;
        return;
    }
    
    void Push_Down(int p, int l, int r) {
        if(mark[p] == -INF) return;
        int mid = (l + r) >> 1;
        Work(p << 1, l, mid, mark[p]);
        Work(p << 1 | 1, mid + 1, r, mark[p]);
        mark[p] = -INF; 
    }
    
    void Build(int p, int l, int r) {
        mark[p] = -INF;
        if(l == r) {
            minx[p] = sum[p] = a[l]; sminx[p] = INF; minnum[p] = 1;
            for(int K = BITS - 1; K >= 0; K --)
                if(a[l] & bits[K]) num[p][K] ++;
            return;
        }
        int mid = (l + r) >> 1;
        Build(p << 1, l, mid), Build(p << 1 | 1, mid + 1, r);
        Push_Up(p, l, r); 
    }
    
    void Modify(int p, int l, int r, int x) {
        if(minx[p] >= x) return;
        if(minx[p] < x && sminx[p] > x) {
            Work(p, l, r, x);
            return;
        }
        int mid = (l + r) >> 1; Push_Down(p, l, r);
        Modify(p << 1, l, mid, x), Modify(p << 1 | 1, mid + 1, r, x);
        Push_Up(p, l, r);
    }
    
    void Update(int p, int l, int r, int L, int R, int x) {
        if(l > R || r < L) return;
        if(L <= l && R >= r) {
            Modify(p, l, r, x);
            return;
        }
        int mid = (l + r) >> 1;
        Push_Down(p, l, r);
        Update(p << 1, l, mid, L, R, x);
        Update(p << 1 | 1, mid + 1, r, L, R, x);
        Push_Up(p, l, r);
    }
    
    int Query(int p, int l, int r, int L, int R) {
        if(l > R || r < L) return 0;
        if(l >= L && r <= R) return sum[p];
        Push_Down(p, l, r);
        int mid = (l + r) >> 1;
        return Query(p << 1, l, mid, L, R) ^ Query(p << 1 | 1, mid + 1, r, L, R); 
    }
    
    int Query2(int p, int l, int r, int L, int R, int x) {
        if(l > R || r < L) return 0;
        if(l >= L && r <= R) return num[p][x];
        Push_Down(p, l, r);
        int mid = (l + r) >> 1;
        return Query2(p << 1, l, mid, L, R, x) + Query2(p << 1 | 1, mid + 1, r, L, R, x);
    }
    
    int main() {
        n = read(), q = read(); bits[0] = 1;
        for(int i = 1; i <= n; i ++) a[i] = read();
        for(int i = 1; i < BITS; i ++) bits[i] = bits[i - 1] << 1;
        Build(1, 1, n);
        for(int i = 1; i <= q; i ++) {
            int op = read(), l = read(), r = read(), x = read();
            if(op == 1) Update(1, 1, n, l, r, x);
            else {
                int S = Query(1, 1, n, l, r) ^ x;
                if(!S) printf("0
    ");
                else {
                    int cnt = -1;
                    while(S) S >>= 1, cnt ++;
                    printf("%d
    ", Query2(1, 1, n, l, r, cnt) + (bool) (x & bits[cnt]));
                }
            }
        }    
        return 0;
    }
     

    M.

    简单树形dp, 状态设置 f[i][j][k(01)] 代表dp到 i 号节点,子树内已经选择了 j 个节点,当前节点选/不选的情况下干掉整个子树内的怪物所需要的最少能量值。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 2005
    #define INF 10000000000000
    #define LL long long
    int n, size[maxn], val[maxn];
    LL g[maxn][maxn][2], f[maxn][maxn][2];
    
    int read() {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct edge {
        int cnp = 1, head[maxn], last[maxn], to[maxn];
        void add(int u, int v) {
            to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
        }
    }E;
    
    void Down(LL &x, LL y) {
        if(y < x) x = y;
    }
    
    void DP(int u) {
        size[u] = 1;
        f[u][0][0] = val[u];
        f[u][1][1] = 0;
        for(int i = E.head[u]; i; i = E.last[i]) {
            int v = E.to[i];
            DP(v);
            for(int t1 = 0; t1 <= size[v]; t1 ++) 
                for(int t2 = 0; t2 <= size[u]; t2 ++) {
                    //down did not choose;
                    Down(g[u][t1 + t2][0], f[v][t1][0] + f[u][t2][0] + val[v]);
                    Down(g[u][t1 + t2][1], f[v][t1][0] + f[u][t2][1]);
                    //down did choose 
                    Down(g[u][t1 + t2][0], f[v][t1][1] + f[u][t2][0]);
                    Down(g[u][t1 + t2][1], f[v][t1][1] + f[u][t2][1]);
                }
            size[u] += size[v];
            for(int t = 0; t <= size[u]; t ++) {
                f[u][t][0] = g[u][t][0], f[u][t][1] = g[u][t][1];
                g[u][t][0] = g[u][t][1] = INF;
            }
        }
    }
    
    int main() {
        int T = read();
        while(T --) {
            n = read(); E.cnp = 1;
            for(int i = 1; i <= n; i ++) E.head[i] = 0;
            for(int i = 2; i <= n; i ++) {
                int x = read();
                E.add(x, i);
            }
            for(int i = 0; i <= n; i ++)
                for(int j = 0; j <= n; j ++)
                    for(int t = 0; t <= 1; t ++)
                        f[i][j][t] = g[i][j][t] = INF;
            for(int i = 1; i <= n; i ++) val[i] = read();
            DP(1);
            for(int i = 0; i < n; i ++) printf("%lld ", min(f[1][i][0], f[1][i][1]));
            printf("%lld
    ", min(f[1][n][0], f[1][n][1]));
        }
        return 0;
    } 

    济南站:

    A.

    列与列之间相互独立,可以拆开来做。每一列都是 n 个 n 元异或方程,求解自由元的个数可以用线性基 + bitset 优化。

    H.

    令 (a_{i}) 为最后一次选择了 (i) 路径上的点的时间,(S) 为 a_{i} 构成的集合。则此时的次数即为 (max(S))。由 min-max 容斥有 (max(S) = sum_{Tsubseteq S}^{}(-1)^{|T| - 1}min(T) ),该式对期望也成立,即 (E(max(S)) = sum_{Tsubseteq S}^{}(-1)^{|T| - 1} E(min(T)) ) 。

    而对于给定的路径集合,E(min(T)) 很容易计算。设一共覆盖的有 m 个点,期望的次数即为 n / m 次。

    考虑转枚举集合 T 为枚举 m, 使用 dp 计算方案。树形 dp 状态: f[i][j][k][s(01)] 代表 dp 到 i 点,子树内覆盖了有 j 个点,已选择的路径向上覆盖了 k 个点,一共选择的路径条数为奇数 /  偶数。我的代码里面把完全覆盖的路径删掉了,但其实可以不用吧……?

    #include <bits/stdc++.h>
    using namespace std;
    #define mod 998244353
    #define maxn 350
    #define maxm 100000
    int n, m, f[maxn][maxn][maxn][2], size[maxn], dep[maxn], len[maxn], R[maxn][maxn];
    int recfa[maxn], g[maxn][maxn][2];
    bool mark[maxn][maxn];
    
    int read() {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    struct node {
        int a, b;
    }e[maxn];
    
    struct edge {
        int cnp = 1, head[maxm], last[maxm], to[maxm], id[maxm];
        void add(int u, int v) {
            to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
        }
    }E, E2;
    
    int add(int x, int y) {
        x += y; if(x >= mod) x -= mod; 
        return x;
    }
    int sub(int x, int y) {
        x -= y; if(x < 0) x += mod;
        return x;
    }
    void Up(int &x, int y) {
        x += y; if(x >= mod) x -= mod;
    }
    int mul(int x, int y) {
        return 1ll * x * y % mod;
    }
    
    int Qpow(int x, int timer) {
        int base = 1;
        for(; timer; timer >>= 1, x = mul(x, x))
            if(timer & 1) base = mul(base, x);
        return base;
    }
    
    bool Check(int u, int gra, int id) {
        if(gra != u) {
            for(int i = E2.head[u]; i; i = E2.last[i]) {
                int v = E2.to[i];
                if(dep[v] < dep[e[id].a]) return 0;
            }
        }
        for(int i = E.head[u]; i; i = E.last[i]) {
            int v = E.to[i];
            if(!Check(v, gra, id)) return 0;
        }
        return 1;
    }
    
    void dfs(int u, int fa) {
        dep[u] = dep[fa] + 1; recfa[u] = fa;
        for(int i = E.head[u]; i; i = E.last[i]) {
            int v = E.to[i];
            dfs(v, u);
        }
    }
    
    void DP(int u, int fa) {
        f[u][0][0][0] = 1; 
        for(int i = 1; i <= R[u][0]; i ++) {
            len[u] = max(len[u], dep[u] - dep[R[u][i]] + 1);
            f[u][1][dep[u] - dep[R[u][i]] + 1][1] ++;
        }
        if(len[u] >= 1) size[u] = 1;
        for(int i = E.head[u]; i; i = E.last[i]) {
            int v = E.to[i];
            DP(v, u);
            for(int s1 = 0; s1 <= size[u]; s1 ++)
                for(int l1 = 0; l1 <= len[u]; l1 ++)
                    for(int t1 = 0; t1 <= 1; t1 ++)
                        for(int s2 = 0; s2 <= size[v]; s2 ++)
                            for(int l2 = 0; l2 <= len[v]; l2 ++)
                                for(int t2 = 0; t2 <= 1; t2 ++) {
                                    int s = s1 + s2;
                                    if((!l1) && (l2 >= 2)) s ++;
                                    int l = max(l1, l2 - 1);
                                    int t = t1 ^ t2;
                                    Up(g[s][l][t], mul(f[u][s1][l1][t1], f[v][s2][l2][t2]));
                                }
            if(!len[u] && ((len[v] - 1) >= 1)) size[u] ++;
            size[u] += size[v]; len[u] = max(len[u], len[v] - 1);
            for(int s = 0; s <= size[u]; s ++)
                for(int l = 0; l <= len[u]; l ++)
                    for(int t = 0; t <= 1; t ++)
                        f[u][s][l][t] = g[s][l][t], g[s][l][t] = 0;
        }
    }
    
    int main() {
        n = read(), m = read();
        for(int i = 2; i <= n; i ++) {
            int x = read();
            recfa[i] = x;
            E.add(x, i);
        }
        dfs(1, 0);
        for(int i = 1; i <= m; i ++) {
            int a = read(), b = read();
            e[i].a = a, e[i].b = b;
            if(mark[a][b]) continue;
            mark[a][b] = 1;
            E2.add(b, a);
        }
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                mark[i][j] = 0;
        for(int i = 1; i <= m; i ++) {
            int a = e[i].a, b = e[i].b;
            if(mark[a][b]) continue;
            mark[a][b] = 1;
            bool flag = true;
            int c = b;
            while(c != recfa[a]) {
                for(int j = E2.head[c]; j; j = E2.last[j]) {
                    if(c == b && E2.to[j] == a) continue;
                    if(dep[E2.to[j]] >= dep[a]) flag = false;
                }
                c = recfa[c];
            }
            if(flag) R[b][++ R[b][0]] = a;
        }
        DP(1, 0);
        int ans = 0;
        for(int i = 1; i <= n; i ++) {
            int even = add(f[1][i][0][0], f[1][i][1][0]);
            int odd = add(f[1][i][0][1], f[1][i][1][1]);
            Up(ans, mul(Qpow(i, mod - 2), sub(odd, even)));
        }
        ans = mul(ans, n);
        printf("%d
    ", ans);
        return 0;
    }

    J.

    官方题解很清晰啦,树是二分图,用两位保证同边的点之间没有连边,不同边的点之间用锁和钥匙的解法。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 200000
    #define int long long
    int n, mark[maxn], a[maxn], rec[maxn], bits[maxn];
    
    int read() {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    
    struct edge {
        int cnp = 1, to[maxn], last[maxn], head[maxn];
        void add(int u, int v) {
            to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
            to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
        }
    }E;
    
    void dfs(int u, int fa) {
        mark[u] = mark[fa] ^ 1;
        for(int i = E.head[u]; i; i = E.last[i]) {
            int v = E.to[i];
            if(v == fa) continue;
            dfs(v, u);
        }
    }
    
    signed main() {
        n = read(); bits[0] = 1;
        for(int i = 1; i < 61; i ++) bits[i] = bits[i - 1] << 1;
        for(int i = 1; i < n; i ++) {
            int x = read(), y = read();
            E.add(x, y);
        }
        dfs(1, 0);
        int cnt = 0;
        for(int i = 1; i <= n; i ++)
            if(!mark[i]) rec[i] = ++ cnt;
        if(cnt > n / 2) {
            cnt = 0;
            for(int i = 1; i <= n; i ++) mark[i] ^= 1;
            for(int i = 1; i <= n; i ++) 
                if(!mark[i]) rec[i] = ++ cnt;
                else rec[i] = 0;
        }
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= 60; j ++) a[j] = 0;
            for(int j = cnt + 3; j <= 60; j ++) a[j] = 1;
            if(!mark[i]) {
                for(int j = 1; j <= cnt; j ++) a[j] = (j == rec[i]) ? 0 : 1;
                a[cnt + 1] = 1;
            }
            else {
                for(int j = E.head[i]; j; j = E.last[j]) {
                    int v = E.to[j];
                    a[rec[v]] = 1;
                }
                a[cnt + 2] = 1;
            }
            int ans = 0;
            for(int j = 1; j <= 60; j ++)
                if(a[j]) ans += bits[j - 1];
            if(i != n) printf("%lld ", ans);
            else printf("%lld
    ", ans);
        }
        return 0;
    }

    K.

    考虑把 a 由高位到低位建到一棵 trie 树上面去。那么一个 S 在第 i 位上面为 1 等价于把第 i + 1 位的两棵子树翻转一次。可以用 f[u][K] 表示 u 的子树里面随便翻转后求第 K 小的最小值。这个可以用 dp 去求。(由于树高为 log 的级别,所以最多 n * log 个状态)。如果没有 S 的上下界限制,易知答案即为 f[1][K]。如果有上下界,则从高位到低位所选定的 S 一定经历几个过程:和 L,R 都相同;和 L, R 中的一个相同;由于不卡位后面没有限制。因为只有 log 位,所以可以暴力枚举都相同的位,剩下的在trie 树上面 dp,最后取最小值。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 3000005
    #define INF 1200000000
    #define BITS 31
    int T[maxn][2], bits[maxn], tot = 1, size[maxn], n, Q, L, R, K, a[maxn];
    int lim;
    vector<int> f[maxn];
    
    int read() {
        int x = 0, k = 1;
        char c; c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void Ins(int x) {
        int now = 1;
        for(int i = BITS - 1; i >= 0; i --) {
            int t = (bool) (x & bits[i]);
            if(!T[now][t]) T[now][t] = ++ tot;
            now = T[now][t];
        } 
        size[now] ++;
    }
    
    void DP(int u, int dig) {
        if(!u) {
            f[u].resize(1, 0);
            return;
        }
        int ch0 = T[u][0], ch1 = T[u][1];
        if(!ch0 && !ch1) {
            f[u].resize(size[u] + 1, 0);
            return;
        }
        DP(ch0, dig - 1), DP(ch1, dig - 1);
        size[u] += size[ch0], size[u] += size[ch1];
        f[u].resize(size[u] + 1);
        for(int i = 1; i <= size[u]; i ++) {
            // choose to be 0 for the next digit
            if(size[ch0] >= i) f[u][i] = f[ch0][i];
            else f[u][i] = f[ch1][i - size[ch0]] + bits[dig - 1];
            
            //choose to be 1
            if(size[ch1] >= i) f[u][i] = min(f[u][i], f[ch1][i]);
            else f[u][i] = min(f[u][i], f[ch0][i - size[ch1]] + bits[dig - 1]);
        }
    }
    
    // lower bound
    int Work(int u, int dig, int K, int opt) {
        if(dig == -1) {
            if(K <= size[u]) return 0;
            else return INF;
        }
        int ans = INF;
        bool t = lim & (bits[dig]);
        int opt1 = opt; if(opt < 0) opt1 = -opt;
        if(size[T[u][t]] >= K) ans = min(ans, Work(T[u][t], dig - 1, K, opt1));
        else ans = min(ans, Work(T[u][t ^ 1], dig - 1, K - size[T[u][t]], opt1) + bits[dig]);
        if(((opt == 1) && !t) || ((opt == 2) && t)) {
            t ^= 1;
            if(size[T[u][t]] >= K) ans = min(ans, f[T[u][t]][K]);
            else ans = min(ans, f[T[u][t ^ 1]][K - size[T[u][t]]] + bits[dig]);
        }
        return ans;
    }
    
    int main() {
        n = read(), Q = read();    bits[0] = 1;
        for(int i = 1; i <= BITS; i ++) bits[i] = bits[i - 1] << 1;
        for(int i = 1; i <= n; i ++) {
            a[i] = read();
            Ins(a[i]);
        }
        DP(1, BITS);
        for(int i = 1; i <= Q; i ++) {
            L = read(), R = read(), K = read();
            int now = 1, x = 0;
            int ans = INF;
            for(int j = BITS - 1; j >= 0; j --) {
                bool t = L & bits[j];
                if((L & bits[j]) == (R & bits[j])) {
                    if(size[T[now][t]] >= K) now = T[now][t];
                    else K -= size[T[now][t]], now = T[now][t ^ 1], x += bits[j];
                }
                if((L & bits[j]) != (R & bits[j])) { 
                    lim = L, ans = min(ans, x + Work(now, j, K, -1));
                    lim = R, ans = min(ans, x + Work(now, j, K, -2));
                    break; 
                }
                else if(j == 0) ans = x;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    L.

    数位dp。因为最多加100,所以在第 7 位至多进位一次。状态 f[x][y][s][t] 代表 dp 到第 x 位,连续的 1  的奇偶性,一共的 1 的奇偶性,是否卡位。最后的 6 位暴力枚举判断是否满足条件。

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long 
    #define maxn 1000
    #define BITS 62
    int m, L, ans, a[maxn], cnt[maxn], bits[maxn], f[maxn][2][2][2];
    
    void Up(int &x, int y) {
        x += y;
    }
    
    // x : digit number; y : consequent 1s'; s : tot 1s' parity; t : upper limitation;
    void trans(int x, int y, int s, int t) {
        int x1 = x - 1; bool num1 = L & bits[x1];
        if(!t || (t && num1)) {
            int y1 = y ^ 1, s1 = s ^ 1, t1 = t;
            Up(f[x1][y1][s1][t1], f[x][y][s][t]);
        }
        int y1 = 0, s1 = s, t1 = t;
        if(t && (num1)) t1 = 0;
        Up(f[x1][y1][s1][t1], f[x][y][s][t]); 
    }
    
    void DP() {
        for(int x = BITS - 1; x >= 7; x --)
            for(int y = 0; y <= 1; y ++)
                for(int s = 0; s <= 1; s ++)
                    for(int t = 0; t <= 1; t ++)
                        f[x][y][s][t] = 0;
        f[BITS - 1][0][0][1] = 1;
        for(int x = BITS - 1; x >= 8; x --)
            for(int y = 0; y <= 1; y ++)
                for(int s = 0; s <= 1; s ++)
                    for(int t = 0; t <= 1; t ++) 
                        if(f[x][y][s][t]) trans(x, y, s, t);
    }
    
    void Cal() {
        int lim = L & (bits[7] - 1); ans = 0;
        for(int y = 0; y <= 1; y ++) {
            for(int s = 0; s <= 1; s ++)
                for(int t = 0; t <= 1; t ++) {
                    int num1 = f[7][y][s][t];
                    if(!num1) continue;
                    for(int i = 0; i < bits[7]; i ++) {
                        if(t && (i > lim)) continue;
                        bool flag = true;
                        int num = i; int s1 = s;
                        for(int j = 0; j < m; j ++, num ++) {
                            if(num >= bits[7]) {
                                if(!y) s1 ^= 1; 
                                num = 0;
                            }
                            if((s1 ^ (cnt[num] & 1)) != a[j]) { flag = false; break; }
                        }
                        if(flag) ans += num1;
                    }
                }
        }
    }
    
    signed main() {
        ios::sync_with_stdio(0); cin.tie(0);
        int T; cin >> T; bits[0] = 1;
        for(int i = 1; i < BITS; i ++) bits[i] = bits[i - 1] << 1;
        for(int i = 0; i < bits[7]; i ++) {
            int x = i;
            while(x) { if(x & 1) cnt[i] ++; x >>= 1; }
        }
        while(T --) {
            cin >> m >> L;
            for(int i = 0; i < m; i ++) cin >> a[i];
            DP();
            Cal();
            cout << ans << endl;
        }
        return 0;
    }
     
  • 相关阅读:
    poj 1159
    poj1102
    在WebDynpro中的table控件中添加Search help的方法
    用Writer写的第一篇日志
    上路
    C# IList, ArrayList与List的区别详解 & 简单用法举例
    诸葛亮为什么难以入围千古名相之列
    Silverlight5.0正式发布附下载地址
    arcgis server 9.3 问题总结[转]
    AO 直接调用GeoProcessing 工具
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/14228701.html
Copyright © 2011-2022 走看看