結果

問題 No.2441 行列累乗
ユーザー AerenAeren
提出日時 2023-08-25 21:23:21
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 2 ms / 2,000 ms
コード長 6,919 bytes
コンパイル時間 3,460 ms
コンパイル使用メモリ 359,168 KB
実行使用メモリ 5,376 KB
最終ジャッジ日時 2024-06-06 15:38:32
合計ジャッジ時間 4,108 ms
ジャッジサーバーID
(参考情報)
judge2 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 1 ms
5,376 KB
testcase_06 AC 2 ms
5,376 KB
testcase_07 AC 1 ms
5,376 KB
testcase_08 AC 2 ms
5,376 KB
testcase_09 AC 2 ms
5,376 KB
testcase_10 AC 1 ms
5,376 KB
testcase_11 AC 1 ms
5,376 KB
testcase_12 AC 2 ms
5,376 KB
testcase_13 AC 2 ms
5,376 KB
testcase_14 AC 2 ms
5,376 KB
testcase_15 AC 2 ms
5,376 KB
testcase_16 AC 1 ms
5,376 KB
testcase_17 AC 2 ms
5,376 KB
testcase_18 AC 1 ms
5,376 KB
testcase_19 AC 2 ms
5,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <x86intrin.h>
#include <bits/stdc++.h>
using namespace std;
#if __cplusplus > 201703L
#include <ranges>
using namespace numbers;
#endif

// T must support +=, -=, *, *=, ==, and !=
template<class T, size_t N, size_t M>
struct matrix_fixed{
	using ring_t = T;
	using domain_t = array<T, M>;
	using range_t = array<T, N>;
	static constexpr int n = N, m = M;
	array<array<T, M>, N> data;
	array<T, M> &operator()(int i){
		assert(0 <= i && i < n);
		return data[i];
	}
	const array<T, M> &operator()(int i) const{
		assert(0 <= i && i < n);
		return data[i];
	}
	T &operator()(int i, int j){
		assert(0 <= i && i < n && 0 <= j && j < m);
		return data[i][j];
	}
	const T &operator()(int i, int j) const{
		assert(0 <= i && i < n && 0 <= j && j < m);
		return data[i][j];
	}
	bool operator==(const matrix_fixed &a) const{
		assert(n == a.n && m == a.m);
		return data == a.data;
	}
	bool operator!=(const matrix_fixed &a) const{
		assert(n == a.n && m == a.m);
		return data != a.data;
	}
	matrix_fixed &operator+=(const matrix_fixed &a){
		assert(n == a.n && m == a.m);
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) data[i][j] += a(i, j);
		return *this;
	}
	matrix_fixed operator+(const matrix_fixed &a) const{
		assert(n == a.n && m == a.m);
		return matrix_fixed(*this) += a;
	}
	matrix_fixed &operator-=(const matrix_fixed &a){
		assert(n == a.n && m == a.m);
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) data[i][j] += a(i, j);
		return *this;
	}
	matrix_fixed operator-(const matrix_fixed &a) const{
		assert(n == a.n && m == a.m);
		return matrix_fixed(*this) += a;
	}
	template<size_t N2, size_t M2>
	matrix_fixed<T, N, M2> operator*(const matrix_fixed<T, N2, M2> &a) const{
		assert(m == a.n);
		int l = M2;
		matrix_fixed<T, N, M2> res;
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) for(auto k = 0; k < l; ++ k) res(i, k) += data[i][j] * a(j, k);
		return res;
	}
	template<size_t N2, size_t M2>
	matrix_fixed &operator*=(const matrix_fixed<T, N2, M2> &a){
		return *this = *this * a;
	}
	matrix_fixed &operator*=(T c){
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) data[i][j] *= c;
		return *this;
	}
	matrix_fixed operator*(T c) const{
		return matrix_fixed(*this) *= c;
	}
	template<class U, typename enable_if<is_integral<U>::value>::type* = nullptr>
	matrix_fixed &inplace_power(U e){
		assert(n == m && e >= 0);
		matrix_fixed res(1, 0);
		for(; e; *this *= *this, e >>= 1) if(e & 1) res *= *this;
		return *this = res;
	}
	template<class U>
	matrix_fixed power(U e) const{
		return matrix_fixed(*this).inplace_power(e);
	}
	matrix_fixed<T, M, N> transposed() const{
		matrix_fixed<T, M, N> res;
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) res(j, i) = data[i][j];
		return res;
	}
	matrix_fixed &transpose(){
		return *this = transposed();
	}
	// Multiply a column vector v on the right
	range_t operator*(const domain_t &v) const{
		range_t res;
		res.fill(T(0));
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) res[i] += data[i][j] * v[j];
		return res;
	}
	// Assumes T is a field
	// find_inverse() must return optional<T>
	// O(n) find_inverse() calls along with O(n^3) operations on T
	T determinant(auto find_inverse) const{
		assert(n == m);
		if(n == 0) return T(1);
		auto a = data;
		T res = T(1);
		for(auto j = 0; j < n; ++ j){
			int pivot = -1;
			for(auto i = j; i < n; ++ i) if(a[i][j] != T(0)){
				pivot = i;
				break;
			}
			if(!~pivot) return T(0);
			swap(a[j], a[pivot]);
			res *= a[j][j] * (j != pivot ? -1 : 1);
			auto invp = find_inverse(a[j][j]);
			assert(invp);
			T inv = *invp;
			for(auto i = j + 1; i < n; ++ i) if(i != j && a[i][j] != T(0)){
				T d = a[i][j] * inv;
				for(auto jj = j; jj < n; ++ jj) a[i][jj] -= d * a[j][jj];
			}
		}
		return res;
	}
	// Assumes T is a field
	// find_inverse() must return optional<T>
	// O(n) find_inverse() calls along with O(n^3) operations on T
	optional<matrix_fixed> inverse(auto find_inverse) const{
		assert(n == m);
		if(n == 0) return *this;
		auto a = data;
		array<array<T, M>, N> res;
		for(auto i = 0; i < n; ++ i) res[i].fill(T(0)), res[i][i] = T(1);
		for(auto j = 0; j < n; ++ j){
			int pivot = -1;
			for(auto i = j; i < n; ++ i) if(a[i][j] != T(0)){
				pivot = i;
				break;
			}
			if(!~pivot) return {};
			swap(a[j], a[pivot]), swap(res[j], res[pivot]);
			auto invp = find_inverse(a[j][j]);
			assert(invp);
			T inv = *invp;
			for(auto jj = 0; jj < n; ++ jj) a[j][jj] *= inv, res[j][jj] *= inv;
			for(auto i = 0; i < n; ++ i) if(i != j && a[i][j] != T(0)){
				T d = a[i][j];
				for(auto jj = 0; jj < n; ++ jj) a[i][jj] -= d * a[j][jj], res[i][jj] -= d * res[j][jj];
			}
		}
		return matrix_fixed(n, n, res);
	}
	template<class output_stream>
	friend output_stream &operator<<(output_stream &out, const matrix_fixed &a){
		out << "{";
		for(auto i = 0; i < a.n; ++ i){
			out << "{";
			for(auto j = 0; j < a.m; ++ j){
				out << a(i, j);
				if(j != a.m - 1) out << ", ";
			}
			out << "}";
			if(i != a.n - 1) out << ", ";
		}
		return out << "}";
	}
	matrix_fixed(): matrix_fixed(T(0), T(0)){ }
	matrix_fixed(const T &init_diagonal, const T &init_off_diagonal){
		for(auto i = 0; i < n; ++ i) for(auto j = 0; j < m; ++ j) data[i][j] = i == j ? init_diagonal : init_off_diagonal;
	}
	matrix_fixed(const array<array<T, M>, N> &arr): data(arr){ }
	static matrix_fixed additive_identity(){
		return matrix_fixed(T(1), T(0));
	}
	static matrix_fixed multiplicative_identity(){
		return matrix_fixed(T(0), T(0));
	}
};
template<class T, size_t N, size_t M>
matrix_fixed<T, N, M> operator*(T c, matrix_fixed<T, N, M> a){
	for(auto i = 0; i < a.n; ++ i) for(auto j = 0; j < a.m; ++ j) a(i, j) = c * a(i, j);
	return a;
}
// Multiply a row vector v on the left
template<class T, size_t N, size_t M>
matrix_fixed<T, N, M>::domain_t operator*(const typename matrix_fixed<T, N, M>::range_t &v, const matrix_fixed<T, N, M> &a){
	typename matrix_fixed<T, N, M>::domain_t res;
	res.fill(T(0));
	for(auto i = 0; i < a.n; ++ i) for(auto j = 0; j < a.m; ++ j) res[j] += v[i] * a(i, j);
	return res;
}

int main(){
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(ios::badbit | ios::failbit);
	matrix_fixed<int, 2, 2> mat(2, 2);
	for(auto i = 0; i < 2; ++ i){
		for(auto j = 0; j < 2; ++ j){
			cin >> mat(i, j);
		}
	}
	mat = mat.power(3);
	for(auto i = 0; i < 2; ++ i){
		for(auto j = 0; j < 2; ++ j){
			cout << mat(i, j) << " ";
		}
		cout << "\n";
	}
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////
0