Disclaimer: This article is a blogger original article, reproduced without the blogger must be allowed. https://blog.csdn.net/qq_35950004/article/details/90383714
Topic
enumeration value, enumerate the number of steps and the last point DP, the enumeration before a transfer point, are only the starting point and end point calculated in line with the value of the program.
The resulting value is the number of programs and their superset, inclusion and exclusion it (you can also call this IFMT) can answer.
time complexity
cycles using Expand +
instead of
to get
accelerated to AC this question.
Loop unrolling too spicy
AC Code:
#include <bits/stdc++.h>
#define maxn 64
#define maxm 20005
#define mod 998244353
#define LL unsigned long long
using namespace std;
int n, m, A[maxn][maxn], B[maxn][maxn], S[maxn], f[2][maxn], ans[maxn][maxm];
inline int add(int a, int b) {
int c = a + b;
return c >= mod ? c - mod : c;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) scanf("%d", &A[i][j]);
for (int x = 0; x < n; x++) {
memset(f, 0, sizeof f);
memset(S, 0, sizeof S);
int now = 1, pre = 0;
for (int i = 0; i < n; i++) {
if ((i & x) == x) {
for (int j = 0; j < n; j++) S[j] = add(S[j], A[i][j]);
f[pre][i] = 1;
}
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) B[i][j] = add(A[i][j], ((i & x) == x) * S[j]);
for (int i = 0; i < n; i++) {
LL ret = 0;
for (int k = 0; k < n; k += 8) {
ret += (LL)f[pre][k] * A[k][i], ret += (LL)f[pre][k + 1] * A[k + 1][i],
ret += (LL)f[pre][k + 2] * A[k + 2][i], ret += (LL)f[pre][k + 3] * A[k + 3][i],
ret += (LL)f[pre][k + 4] * A[k + 4][i], ret += (LL)f[pre][k + 5] * A[k + 5][i],
ret += (LL)f[pre][k + 6] * A[k + 6][i], (ret += (LL)f[pre][k + 7] * A[k + 7][i]) %= mod;
}
f[now][i] = ret;
if ((i & x) == x)
ans[x][1] = add(ans[x][1], ret);
}
swap(now, pre);
for (int j = 2; j <= m; j++, swap(now, pre))
for (int i = 0; i < n; i++) {
LL ret = 0;
for (int k = 0; k < n; k += 8) {
ret += (LL)f[pre][k] * B[k][i], ret += (LL)f[pre][k + 1] * B[k + 1][i],
ret += (LL)f[pre][k + 2] * B[k + 2][i], ret += (LL)f[pre][k + 3] * B[k + 3][i],
ret += (LL)f[pre][k + 4] * B[k + 4][i], ret += (LL)f[pre][k + 5] * B[k + 5][i],
ret += (LL)f[pre][k + 6] * B[k + 6][i],
(ret += (LL)f[pre][k + 7] * B[k + 7][i]) %= mod;
}
f[now][i] = ret;
if ((i & x) == x)
ans[x][j] = add(ans[x][j], ret);
}
}
for (int bit = 1; bit < n; bit <<= 1)
for (int i = 0; i < n; i++)
if (i & bit)
for (int j = 1; j <= m; j++) ans[i - bit][j] = add(ans[i - bit][j], mod - ans[i][j]);
int res = 0;
for (int i = 0; i < n; i++)
for (int j = 1; j <= m; j++) res ^= ans[i][j];
printf("%d\n", res);
}