CCF 201512-5 矩阵_50分_矩阵快速幂

CCF 201512-5 矩阵 传送门

这道题看上去好像可以用变形的矩阵快速幂求解, 但是最大数据范围m = 1000,n = 100,k ≤ 1e9, 常规的算法复杂度*O(m^3*n*logk)*肯定是不可以了, 高达1e12级数. 但是较小的数据还是可以过掉的.

我得了50分, 过掉了较小的数据, 在百度上没有找到有谁发出100分的代码, 自己也暂时想不出正解.

这里的变形, 是矩阵元素的加法变成了xor, 乘法变成了&. 而我想, 正解一定和这两个变化脱不了干系.

我们来分析下复杂度, 对于每次查询, 次数有1e9之高, 效率最高的是logK, 那么不可省去的复杂度是n logK, 大约3000, 时限是1s,所以另一个复杂度不超过mlogm. 普通的矩阵进行一次乘法是O(n^3), 但这里每个元素位是0 或 1, 而且又定义了xor为加法,&为乘法,所以一定是把一行当作一个数来处理的, 因为两个整数的位运算是位与位之间的运算, 而这一步, 就压缩了一个线性的复杂度. 不过至于具体的算法或者说技巧, 我并不知道.

当然, 我的思路是基于类矩阵快速幂方法的, 但是可能所谓正解, 其实是一条决然不同的路.

要拿50分很简单, 做出正解, 才是真正的大佬.

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

int matrix[1005][1005], b[1005], n, m;
int E[1005][1005], matr[1005][1005], ans[1005];
int ano[1005][1005];
char ch_matrix[1005];

void multi(int E[1005][1005], int ano[1005][1005], int matr[1005][1005])
{
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            E[i][j] = (ano[i][1] & matr[1][j]);
            for (int k = 2; k <= n; ++k) {
                E[i][j] ^= (ano[i][k] & matr[k][j]);
            }
        }
    }
}

void mul(int E[1005][1005], int b[1005], int ans[1005])
{
    memset(ans, 0, sizeof(ans));
    for (int i = 1; i <= n; ++i) {
        ans[i] = E[i][1] & b[1];
        //cout << ans[i] << ' ';
        for (int j = 2; j <= n; ++j) {
            ans[i] ^= E[i][j] & b[j];
        //  cout << ans[i] << ' ';
        }
        //cout << endl;
        //cout << "ans[" << i << "] = " << ans[i] << endl;
    }
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> ch_matrix[j];
            matrix[i][j] = ch_matrix[j] - '0';
        }
    }
    for (int i = 1; i <= n; ++i) {
        cin >> ch_matrix[i];
        b[i] = ch_matrix[i] - '0';
    }
    cin >> m;
    for (int i = 0; i < m; ++i) {
        int k;
        cin >> k;
        for (int i  = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                matr[i][j] = matrix[i][j]; // 原矩阵
            }
        }
        memset(E, 0, sizeof(E));
        for (int j = 1; j <= n; ++j) {
            E[j][j] = 1; // 单位矩阵
        }
        while (k) {
            if (k & 1) {
                for (int i = 1; i <= n; ++i) {
                    for (int j = 1; j <= n; ++j) {
                        ano[i][j] = E[i][j];
                    }
                }
                multi(E, ano, matr);
            }
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    ano[i][j] = matr[i][j];
                }
            }
            multi(matr, ano, ano);
            k >>= 1;
        }
        mul(E, b, ans);
        /*cout << "---------matrix---------" << endl;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                cout << E[i][j];
            }
            cout << endl;
        }
        cout << "ans:  ";*/
        for (int i = 1; i <= n; ++i) {
            cout << ans[i];
        }
        cout << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/81561656