[THUPC2019]找树
见生成树想到矩阵树
考虑答案范围很小,可以枚举然后算是否有生成树符合条件。
考虑一整棵树的贡献,实际上按位做位运算卷积。而矩阵树定理本质是树边权乘积之和,注意到卷积也满足乘法运算的性质,也就是我们可以把矩阵里每一个元素看成多项式。
求行列式就是FWT一遍,求行列式然后IFWT.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1 << 12, mod = 998244353, inv2 = 499122177;
int a[75][75][N + 5], f[75][75], n, m, w, c[N + 5];
string s;
inline void FWT(int *f, int n, int flag) {
for (int i = 2, j = 1, b = 0; i <= n; i <<= 1, j <<= 1, ++b) {
if (s[b] == '|') {
for (int k = 0; k < n; k += i)
for (int l = 0; l < j; ++l) {
int del = 1ll * f[k + l] * flag % mod;
if (del < 0) del += mod;
f[j + k + l] += del;
if (f[j + k + l] >= mod) f[j + k + l] -= mod;
}
} else if (s[b] == '&') {
for (int k = 0; k < n; k += i)
for (int l = 0; l < j; ++l) {
int del = 1ll * f[j + k + l] * flag % mod;
if (del < 0) del += mod;
f[k + l] += del;
if (f[k + l] >= mod) f[k + l] -= mod;
}
} else {
for (int k = 0; k < n; k += i)
for (int l = 0; l < j; ++l) {
f[k + l] += f[j + k + l];
f[j + k + l] = (f[k + l] - (f[j + k + l] << 1)) % mod;
if (f[j + k + l] < 0) f[j + k + l] += mod;
f[k + l] = 1ll * f[k + l] * flag % mod; f[j + k + l] = 1ll * f[j + k + l] * flag % mod;
if (f[k + l] < 0) f[k + l] += mod;
if (f[j + k + l] < 0) f[j + k + l] += mod;
}
}
}
}
inline int power(int a, int b) {
register int k = b, y = a, t = 1;
while (k) {
if (k & 1) t = (1ll * t * y) % mod;
y = (1ll * y * y) % mod; k >>= 1;
} return t;
}
inline int det() {
register int ans = 1, sg = 1;
for (register int i = 1; i < n; ++i) {
for (register int j = i + 1; j < n; ++j) {
while (f[j][i]) {
const int tmp = f[i][i] / f[j][i];
if (tmp)
for (register int k = i; k < n; ++k)
f[i][k] = ((1ll * f[i][k] - (1ll * tmp * f[j][k]) % mod) % mod + mod) % mod;
swap(f[i], f[j]); sg = -sg;
}
} if (!f[i][i]) return 0;
ans = (1ll * ans * f[i][i]) % mod;
}
return ((sg * ans) % mod + mod) % mod;
}
inline int read() {
register int s = 0; register char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) s = (s << 1) + (s << 3) + (ch & 15), ch = getchar();
return s;
}
int main() {
n = read(); m = read();
cin >> s; w = s.length();
for (int i = 1, x, y, v; i <= m; ++i) {
x = read(); y = read(); v = read();
--a[x][y][v]; --a[y][x][v];
++a[x][x][v]; ++a[y][y][v];
}
for (int i = 1; i < n; ++i) {
for (int j = 1; j < n; ++j)
for (int k = 0; k < (1 << w); ++k)
if (a[i][j][k] < 0) a[i][j][k] += mod;
}
for (int i = 1; i < n; ++i)
for (int j = 1; j < n; ++j)
FWT(a[i][j], 1 << w, 1);
for (int k = 0; k < (1 << w); ++k) {
for (int i = 1; i < n; ++i)
for (int j = 1; j < n; ++j)
f[i][j] = a[i][j][k];
c[k] = det();
} FWT(c, 1 << w, -1);
for (int i = (1 << w) - 1; ~i; --i)
if (c[i]) {
printf("%d", i);
return 0;
}
puts("-1");
return 0;
}

浙公网安备 33010602011771号