LOJ # 2463. Perfect Trip "2018 Team interoperability test Day 1" (currently only loop unrolling Dafa)

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 O ( n 3 m ) O (n ^ 3m)
cycles using Expand + unsigned   long   long \texttt{unsigned long long} instead of long   long \texttt{long long} to get 1000ms \texttt{1000ms} 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);
}

Guess you like

Origin blog.csdn.net/qq_35950004/article/details/90383714