#include<bits/stdc++.h> #define ll long long // Support: // Matrix multiplication // Solving system of equations template <typename T> struct Matrix { vector< vector<T> > data; int nrow, ncol; T MMOD; Matrix (int nrow_, int ncol_, T MMOD_=-1) : nrow(nrow_), ncol(ncol_), MMOD(MMOD_) { data.clear(); data.resize(nrow, vector<T>(0, 0)); for (int i = 0; i < nrow; ++i) { data[i].resize(ncol, 0); } } Matrix (int nrow_, int ncol_, vector< vector<T> > data_, T MMOD_=-1) : nrow(nrow_), ncol(ncol_), data(data_), MMOD(MMOD_) {} Matrix<T> (const Matrix<T> &mt) { nrow = mt.nrow; ncol = mt.ncol; data = mt.data; MMOD = mt.MMOD; } static Matrix identityMatrix(int nrow, int ncol, T MMOD_) { Matrix<T> m (nrow, ncol, MMOD_); for (int i = 0; i < nrow; ++i) m.data[i][i] = 1; return m; } Matrix operator * (Matrix b) const { if (ncol != b.nrow) { cout << "multiplication error: matrices' size not valid \n"; return Matrix(0, 0, MMOD); } Matrix<T> res(nrow, b.ncol, MMOD); for (int i = 0; i < nrow; ++i) for (int j = 0; j < b.ncol; ++j) for (int k = 0; k < ncol; ++k) { res.data[i][j] += data[i][k]*b.data[k][j]; if (MMOD > 0 && (res.data[i][j] > MMOD || res.data[i][j] < 0)) res.data[i][j] = ((res.data[i][j] % MMOD) + MMOD) % MMOD; } return res; } Matrix pow(ll exp) { if (ncol != nrow) { cout << "Power error: matrices' size not valid \n"; return Matrix(0, 0, MMOD); } if (exp == 0) return identityMatrix(nrow, ncol, MMOD); if (exp == 1) // return (*this); return Matrix<T> (nrow, ncol, data, MMOD); Matrix res = pow(exp >> 1); res = res * res; if (exp & 1) res = res * (*this); // cout << "exp: " << exp << endl; // res.print(); return res; } vector<double> solveSystemEquations() { // Use Gauss-Elimination // Intend to solve system of linear equations of form: // // a[0][0]*x[0] + a[0][1]*x[1] + a[0][2]*x[2] + ... + a[0][n-1]*x[n-1] = a[0][n] // a[1][0]*x[0] + a[1][1]*x[1] + a[1][2]*x[2] + ... + a[1][n-1]*x[n-1] = a[1][n] // ... // a[n-1][0]*x[0] + a[n-1][1]*x[1] + a[n-1][2]*x[2] + ... + a[n-1][n-1]*x[n-1] = a[n-1][n] // // (n rows and n+1 columns) // pre-check T tmp = 1.1; if (tmp == 1) { cout << "Matrix is of type int (or long long) which is not suitable for gauss-elimination \n"; } auto gdata = data; // do gauss-elimination for (int i = 0; i < nrow; ++i) { int pivot = i; for (int j = i+1; j < nrow; ++j) if (fabs(gdata[j][i]) > fabs(gdata[pivot][i])) pivot = j; if (pivot != i) swap(gdata[i], gdata[pivot]); if (fabs(gdata[i][i]) < EPS) continue; for (int k = ncol-1; k >= i; k--) gdata[i][k] /= gdata[i][i]; for (int j = i+1; j < nrow; ++j) { for (int k = ncol-1; k >= i; --k) gdata[j][k] -= gdata[j][i] * gdata[i][k]; } } // find x[0..n-1] for (int i = nrow-2; i >= 0; --i) { if (fabs(gdata[i][i]) > EPS) // means: if gdata[i][i] == 1 for (int k = i+1; k < ncol-1; ++k) if (isfinite(gdata[i][k])) gdata[i][ncol-1] -= gdata[i][k] * gdata[k][ncol-1]; else { gdata[i][ncol-1] = NAN; } } vector<double> x; for (int i = 0; i < nrow; ++i) { x.push_back(gdata[i][ncol-1]); } return x; } void print() { cout << "print matrix " << nrow << " x " << ncol << endl; for (int i = 0; i < nrow; ++i) { for (int j = 0; j < ncol; ++j) cout << data[i][j] << " "; cout << "\n"; } } };