[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号
浙公网安备 33010602011771号