Explosion 【HDU - 5036】【bitset优化矩阵乘法】

题目链接


  有两个大小为N * N的矩阵,我们现在想知道它们的乘积是多少。

  首先,因为要对答案去取模,并且这个模数极其特殊,大致就知道如果直接暴力矩阵乘法(O(N^{3}))是一定会TLE的(试过了…… )

  然后,就是优化了,我们现在看一下0、1、2两两相乘有什么特殊的情况:

const short int dir[3][3] =
{
    0, 0, 0,
    0, 1, 2,
    0, 2, 1
};

  也就是说,遇上1、2这两个数,当它们两相等的时候,相乘的答案为1,不等的时候相乘的答案为2,那么,我们似乎可以用bitset<800>(因为N==800)来维护一下这个。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 805;
const short int dir[3][3] =
{
    0, 0, 0,
    0, 1, 2,
    0, 2, 1
};
inline void solve(int &x) { while(x >= 3) x -= 3; }
int N;
int A[maxN][maxN], B[maxN][maxN], C[maxN][maxN];
bitset<800> r[801][2], u[801][2], t;
int main()
{
    while(scanf("%d", &N) != EOF)
    {
        for(int i=0; i<N; i++)
        {
            r[i][0].reset(); r[i][1].reset();
            u[i][0].reset(); u[i][1].reset();
        }
        for(int i=0; i<N; i++) for(int j=0; j<N; j++)
        {
            scanf("%d", &A[i][j]); A[i][j] %= 3;
            if(A[i][j] & 1)
            {
                r[i][0].set(j);
            }
            else if(A[i][j] & 2)
            {
                r[i][1].set(j);
            }
        }
        for(int i=0; i<N; i++) for(int j=0; j<N; j++)
        {
            scanf("%d", &B[i][j]); B[i][j] %= 3;
            if(B[i][j] & 1)
            {
                u[j][0].set(i);
            }
            else if(B[i][j] & 2)
            {
                u[j][1].set(i);
            }
        }
        for(int i=0; i<N; i++)
        {
            for(int j=0, val; j<N; j++)
            {
                t = r[i][0] & u[j][0];
                val = (int)t.count();   solve(val);
                t = r[i][1] & u[j][1];
                val += (int)t.count();  solve(val);
                t = r[i][0] & u[j][1];
                val += (int)t.count() * 2;  solve(val);
                t = r[i][1] & u[j][0];
                val += (int)t.count() * 2;  solve(val);
                C[i][j] = val;
            }
        }
        for(int i=0; i<N; i++)
        {
            for(int j=0; j<N; j++) printf("%d%c", C[i][j], j == N - 1 ? '\n' : ' ');
        }
    }
    return 0;
}
发布了722 篇原创文章 · 获赞 891 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/103851479