2018东北四省赛 Store The Matrix (矩阵)

题目描述

Given a matrix M with r rows and c columns. It is obviously that we need r × c elements to store this matrix.
However, for a specifi  matrix M , we may be able to represent M as “Matrix-chain multiplication” likes M = A1 ×A2···×An, where n ≥ 1 and each Ai is a matrix with size ri ×ci. Then we can use (***)elements to store {A1, A2 . . . , An} instead of storing M directly.
We want to know: if we represent M in the optimal way, how many elements are needed at least to store M ?

输入

Input is given from Standard Input in the following format:
r c
M1,1 M1,2  . . . M1,c
M2,1 M2,2  . . . M2,c
...
Mr,1 Mr,2  . . . Mr,c
Constraints
1 ≤ r, c ≤ 30
0 ≤ Mi,j ≤ 1000(1 ≤ i ≤ r, 1 ≤ j ≤ c) (Note that although all Mi,j are non-negative integers in the input, we think the element type is float number with infinity precision and can be negative) .

输出

Print one integer denotes the minimal number of elements needed.

样例输入

3 3
1 0 1
0 0 0
1 0 1

样例输出

6

提示

 
 
大胆假设,不会证明。假设矩阵的秩为s,则一个矩阵可表示为一个r*s的矩阵乘以一个s*c的矩阵,第一个矩阵再向下分解只会让元素变多,第二个矩阵为满秩矩阵。
 
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 110;
int n, m, a[N][N], b[N][N], P;

int Pow(int x, int t) {
    int r = 1;
    for (; t; t >>= 1, x = ll(x) * x % P)
        if (t & 1)r = ll(r) * x % P;
    return r;
}

int inv(int x) {
    return Pow(x, P - 2);
}

void pp(int &x, int d) {
    if ((x += d) >= P)x -= P;
}

int Rank() {
    P = 1e9 + 7;
    int rk = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            b[i][j] = a[i][j];
    for (int i = 0, j = 0; i < n && j < m; ++i, ++j) {
        int c = -1;
        for (int k = i; k < n; k++)
            if (b[k][j]) {
                c = k;
                break;
            }
        if (c == -1) --i;
        else {
            ++rk;
            for (int k = j; k < m; k++)
                swap(b[i][k], b[c][k]);
            int cof = inv(b[i][j]);
            for (int k = j; k < m; k++)
                b[i][k] = ll(b[i][k]) * cof % P;
            for (int x = i + 1; x < n; x++)
                if (b[x][j])
                    for (int y = m - 1; y >= j; y--)
                        pp(b[x][y], P - ll(b[x][j]) * b[i][y] % P);
        }
    }
    return rk;
}

int main() {
    //freopen("input.txt", "r", stdin);
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];
    int ra = max(1, Rank());
    cout << min(n * m, (n + m) * ra) << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/albert-biu/p/9597153.html