整整齐齐全是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
", 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