12tqian's Competitive Programming Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub 12tqian/cp-library

:heavy_check_mark: verify/kattis/kattis-equationsolver-matrix.test.cpp

Depends on

Code

#define PROBLEM "https://open.kattis.com/problems/equationsolver"

#include "../../library/contest/template-minimal.hpp"
#include "../../library/numerical/matrix.hpp"

// kattis

int main() {
	using namespace std;
	using namespace MatrixOperations;
	using Mat = Matrix<long double>;
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while (true) {
		int n; cin >> n;
		if (n == 0) break;
		Mat a = make_matrix<long double>(n, n);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				cin >> a[i][j];
			}
		}
		vector<long double> b(n);
		for (int i = 0; i < n; i++) {
			cin >> b[i];
		}
		const long double EPS = 1e-12;
		auto res = solve_linear(a, b, EPS);
		if (res.empty()) {
			cout << "inconsistent\n";
		} else if ((int)res.size() > 1) {
			cout << "multiple\n";
		} else {
			for (auto& t : res[0]) 
				cout << t << " ";
			cout << '\n';
		}
	}
	return 0;
}
#define PROBLEM "https://open.kattis.com/problems/equationsolver"


#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <iomanip>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

template <class D> struct Matrix : std::vector<std::vector<D>> {
	using std::vector<std::vector<D>>::vector;

	int h() const { return int(this->size()); }
	int w() const { return int((*this)[0].size()); }

	Matrix operator*(const Matrix& r) const {
		assert(w() == r.h());
		Matrix res(h(), std::vector<D>(r.w()));
		for (int i = 0; i < h(); i++) {
			for (int j = 0; j < r.w(); j++) {
				for (int k = 0; k < w(); k++) {
					res[i][j] += (*this)[i][k] * r[k][j];
				}
			}
		}
		return res;
	}

	Matrix<D>& operator+=(const Matrix& r) {
		assert(h() == r.h() && w() == r.w());
		for (int i = 0; i < h(); i++) {
			for (int j = 0; j < h(); j++) {
				(*this)[i][j] += r[i][j];
			}
		}
		return *this;
	}

	Matrix& operator-=(const Matrix& r) {
		assert(h() == r.h() && w() == r.w());
		for (int i = 0; i < h(); i++) {
			for (int j = 0; j < h(); j++) {
				(*this)[i][j] -= r[i][j];
			}
		}
		return *this;
	}

	Matrix operator*(const D& r) const {
		Matrix res = (*this);
		for (int i = 0; i < h(); ++i) {
			for (int j = 0; j < w(); ++j) {
				res[i][j] *= r;
			}
		}
		return res;
	}

	Matrix operator/(const D &r) const{ return *this * (1 / r); }
	Matrix& operator*=(const Matrix& r) { return *this = *this * r; }
	Matrix operator+(const Matrix& r) { return *this += r; }
	Matrix operator-(const Matrix& r) { return *this -= r; }
	Matrix& operator*=(const D& r) { return *this = *this * r; }
	Matrix& operator/=(const D &r) { return *this = *this / r; }
	friend Matrix operator*(const D& r, Matrix m) { return m *= r; }

	Matrix pow(long long n) const {
		assert(h() == w());
		Matrix x = *this, r(h(), std::vector<D>(w()));
		for (int i = 0; i < h(); i++) r[i][i] = D(1);
		while (n) {
			if (n & 1) r *= x;
			x *= x;
			n >>= 1;
		}
		return r;
	}
};

namespace MatrixOperations {

template <class T> Matrix<T> make_matrix(int r, int c) { return Matrix<T>(r, std::vector<T>(c)); }

template <class D> int get_row(Matrix<D>& m, int r, int i, int nxt, const D& EPS = -1) {
	std::pair<D, int> best = {0, -1};
	for (int j = nxt; j < r; j++) {
		if (EPS == D(-1) && m[j][i] != 0) {
			return j;
		}
		auto v = m[j][i];
		if (v < 0) v = -v;
		best = std::max(best, std::make_pair(v, j));
	}
	return best.first < EPS ? -1 : best.second;
}

// returns a pair of determinant, rank, while doing Gaussian elimination to m

template <class D> std::pair<D, int> gauss(Matrix<D>& m, const D& EPS = -1) {
	int r = m.h();
	int c = m.w();
	int rank = 0, nxt = 0;
	D prod = 1;
	for (int i = 0; i < r; i++) {
		int row = get_row(m, r, i, nxt, EPS);
		if (row == -1) {
			prod = 0;
			continue;
		}
		if (row != nxt) {
			prod *= -1;
			m[row].swap(m[nxt]);
		}
		prod *= m[nxt][i];
		rank++;
		D x = 1 / m[nxt][i];
		for (int k = i; k < c; k++) 
			m[nxt][k] *= x;
		for (int j = 0; j < r; j++) {
			if (j != nxt) {
				D v = m[j][i];
				if (v == 0) continue;
				for (int k = i; k < c; k++) {
					m[j][k] -= v * m[nxt][k];
				}
			}
		}
		nxt++;
	}
	return {prod, rank};
}

template <class D> Matrix<D> inv(Matrix<D> m, const D& EPS = -1) {
	int r = m.h();
	assert(m.h() == m.w());
	Matrix<D> x = make_matrix<D>(r, 2 * r);
	for (int i = 0; i < r; i++) {
		x[i][i + r] = 1;
		for (int j = 0; j < r; j++) {
			x[i][j] = m[i][j];
		}
	}
	if (gauss(x, EPS).second != r) return Matrix<D>();
	Matrix<D> res = make_matrix<D>(r, r);
	for (int i = 0; i < r; i++) {
		for (int j = 0; j < r; j++) {
			res[i][j] = x[i][j + r];
		}
	}
	return res;
}

template <class D> int calc_rank(Matrix<D> a, const D& EPS = -1) { return gauss(a, EPS).second; }
template <class D> D calc_det(Matrix<D> a, const D& EPS = -1) { return gauss(a, EPS).first; }

template <class D> std::vector<std::vector<D>> solve_linear(Matrix<D> a, std::vector<D> b, const D& EPS = -1) {
	int h = a.h(), w = a.w();
	assert(int(b.size()) == h);
	int r = 0;
	std::vector<bool> used(w);
	std::vector<int> idxs;
	for (int x = 0; x < w; x++) {
		int my = get_row(a, h, x, r, EPS);
		if (my == -1) continue;
		if (r != my) std::swap(a[r], a[my]);
		std::swap(b[r], b[my]);
		for (int y = r + 1; y < h; y++) {
			if (!a[y][x]) continue;
			auto freq = a[y][x] / a[r][x];
			for (int k = x; k < w; k++) a[y][k] -= freq * a[r][k];
			b[y] -= freq * b[r];
		}
		r++;
		used[x] = true;
		idxs.push_back(x);
		if (r == h) break;
	}
	auto zero = [&](const D& x) {
		return EPS == D(-1) ? x == 0 : -EPS < x && x < EPS;
	};
	for (int y = r; y < h; y++) {
		if (!zero(b[y])) return {};
	}
	std::vector<std::vector<D>> sols;
	{ // initial solution

		std::vector<D> v(w);
		for (int y = r - 1; y >= 0; y--) {
			int f = idxs[y];
			v[f] = b[y];
			for (int x = f + 1; x < w; x++) {
				v[f] -= a[y][x] * v[x];
			}
			v[f] /= a[y][f];
		}
		sols.push_back(v);
	}
	for (int s = 0; s < w; s++) {
		if (used[s]) continue;
		std::vector<D> v(w);
		v[s] = D(1);
		for (int y = r - 1; y >= 0; y--) {
			int f = idxs[y];
			for (int x = f + 1; x < w; x++) {
				v[f] -= a[y][x] * v[x];
			}
			v[f] /= a[y][f];
		}
		sols.push_back(v);
	}
	return sols;
}

} // MatrixOperations

// kattis

int main() {
	using namespace std;
	using namespace MatrixOperations;
	using Mat = Matrix<long double>;
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	while (true) {
		int n; cin >> n;
		if (n == 0) break;
		Mat a = make_matrix<long double>(n, n);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				cin >> a[i][j];
			}
		}
		vector<long double> b(n);
		for (int i = 0; i < n; i++) {
			cin >> b[i];
		}
		const long double EPS = 1e-12;
		auto res = solve_linear(a, b, EPS);
		if (res.empty()) {
			cout << "inconsistent\n";
		} else if ((int)res.size() > 1) {
			cout << "multiple\n";
		} else {
			for (auto& t : res[0]) 
				cout << t << " ";
			cout << '\n';
		}
	}
	return 0;
}
Back to top page