省选测试40


整整齐齐全是0

A 献给逝去的公主七重奏

题目大意 : 给一颗树,每次的操作是将每个数该为字数的异或和,问若干次操作之后根的值是多少

  • 记f[i][j] 表示进行i次操作之后,一个节点对它向上第j个祖先是否产生影响。

  • 注意到f[i][j] = f[i][j−1] ^ f[i−1][j] ,这个东西本质上是从(1, 0)到(i, j)的路径数的奇偶性,所以只有在(i-1)&j==0的时候f[i][j]为1

  • 所以在进行了t次操作后,只有深度d&(t-1)==0的点对跟有贡献,那么d|(s(t-1))==(s(t-1))的点都没有贡献,

  • 所以做个高维前缀和,预处理出i的子集的和,拿总的减去没贡献的就行

Code

Show Code
#include <cstdio>

using namespace std;
const int N = 1 << 18 | 5;

int read(int x = 0, int f = 1, char c = getchar()) {
    for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
    for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
    return x * f;
}

struct Edge {
    int n, t;
}e[N*2];
int h[N], edc;

void Add(int x, int y) {
    e[++edc] = (Edge) {h[x], y}; h[x] = edc;
}

int n, m, S, a[N], s[N], mx, k;

void Dfs(int x, int fa, int d) {
    if (d > mx) mx = d;
    s[d] ^= a[x]; d++;
    for (int i = h[x], y; i; i = e[i].n)
        if ((y = e[i].t) != fa) Dfs(y, x, d);
}

int main() {
    freopen("remilia.in", "r", stdin);
    freopen("remilia.out", "w", stdout);
    n = read(); m = read();
    for (int i = 1; i < n; ++i) {
        int x = read(), y = read();
        Add(x, y); Add(y, x);
    }
    for (int i = 1; i <= n; ++i)
        a[i] = read();
    Dfs(1, 0, 0); S = 1;
    while (S <= mx) S *= 2, k++; S--;
    for (int i = 0; i <= k; ++i)
        for (int x = 0; x <= S; ++x)
            if (x & 1 << i) s[x] ^= s[x^(1<<i)];
    while (m--) printf("%d\n", s[((read()-1)&S)^S]);
    return 0;
}

B 优雅地绽放吧,墨染的樱花 (Unaccepted)

题目大意 : n个点,i,j两点间有w[i]*w[j]条边,问所有生成树每个点度数积的和

  • purfer序列行列式推一下

Code

Show Code

C 竹取飞翔 (Unaccepted)

题目大意 :

Code

Show Code
posted @ 2021-03-21 20:39  Shawk  阅读(28)  评论(0编辑  收藏  举报