Xmas Contest 2021 D Determinant?

Amitsur-Levitzki 定理,当 \(n\ge 2k\) 时,答案为 \(0\) 矩阵。

否则我们考虑答案矩阵的某一位 \(b_{i,j}\),其必然由某些路径 \(i=p_0\to p_1\to\ \cdots \to p_n=j\) 贡献而来,一条路径的贡献为 \(\text{sgn}(\sigma)\cdot \prod\limits_{i=1}^nA_{\sigma(i),p_{i-1},p_{i}}\)

于是直接 dp,类似状压求行列式,记录当前 \(\sigma\) 中的 \(A\) 矩阵集合,dp 的值为一个矩阵,表示目前的 \(\text{sgn}(\sigma)\prod A_{\sigma(i)}\)。每次转移进行一次矩阵乘法。复杂度 \(O(2^nnk^3)=O(4^kk^4)\)

// Problem: Determinant?
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/AT_xmascon21_d
// Memory Limit: 1 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define eb emplace_back
#define pb pop_back
#define mt make_tuple
#define mp make_pair
#define fi first
#define se second

using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int> tu;
bool Mbe;

const int N = 20;
const int M = 10;
const int T = (1 << 15) + 5;
const int P = 998244353;

int n, m, S;
int a[N][M][M], f[T][M][M];

void solve() {
	cin >> n >> m;
	if (2 * m <= n) {
		for (int i = 0; i < m; i++, cout << '\n')
			for (int j = 0; j < m; j++)
				cout << 0 << ' ';
		return;
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			for (int k = 0; k < m; k++)
				cin >> a[i][j][k];
	S = (1 << n) - 1;
	for (int i = 0; i < m; i++) f[0][i][i] = 1;
	for (int s = 0; s < S; s++) {
		for (int i = 0; i < n; i++) {
			if ((s >> i) & 1) continue;
			int w = (__builtin_popcount(s >> i) & 1) ? (P - 1) : 1;
			for (int j = 0; j < m; j++) 
				for (int k = 0; k < m; k++)
					for (int l = 0; l < m; l++)
						(f[s | (1 << i)][j][k] += 1ll * f[s][j][l] * w % P * a[i][l][k] % P) %= P;
		}
	}
	for (int i = 0; i < m; i++, cout << '\n')
		for (int j = 0; j < m; j++)
			cout << f[S][i][j] << ' ';
}

bool Med;
int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cerr << (&Mbe - &Med) / 1048576.0 << " MB\n";
	#ifdef FILE
		freopen("1.in", "r", stdin);
		freopen("1.out", "w", stdout);
	#endif
	int T = 1;
	// cin >> T;
	while (T--) solve();
	cerr << (int)(1e3 * clock() / CLOCKS_PER_SEC) << " ms\n";
	return 0;
}
posted @ 2024-01-24 11:10  Ender_32k  阅读(8)  评论(0编辑  收藏  举报