社区讨论
求出高斯消元求解一次多项式行列式
学术版参与者 1已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @m4tx6bln
- 此快照首次捕获于
- 2024/12/18 21:19 去年
- 此快照最后确认于
- 2025/11/04 12:39 4 个月前
我不知道这么写有道理吗?
C#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <sstream>
#include <tuple>
#include <utility>
#include <vector>
template <typename Tp>
using Matrix = std::vector<std::vector<Tp>>;
template <typename Tp>
inline int width(const Matrix<Tp> &A) {
return A.empty() ? 0 : (int)A[0].size();
}
template <typename Tp>
inline int height(const Matrix<Tp> &A) {
return A.size();
}
template <typename Tp>
inline bool is_square_matrix(const Matrix<Tp> &A) {
return width(A) == height(A);
}
template <typename Tp>
inline Matrix<Tp> transpose(const Matrix<Tp> &A) {
const int w = width(A);
const int h = height(A);
Matrix<Tp> TA(w, std::vector<Tp>(h));
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) TA[j][i] = A[i][j];
return TA;
}
template <typename Tp>
inline std::vector<Tp> mat_apply(const Matrix<Tp> &A, const std::vector<Tp> &b) {
const int w = width(A);
const int h = height(A);
assert((int)b.size() == w);
std::vector<Tp> Ab(h);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) Ab[i] += A[i][j] * b[j];
return Ab;
}
template <typename Tp>
inline Matrix<Tp> mat_mul(const Matrix<Tp> &A, const Matrix<Tp> &B) {
const int wA = width(A);
const int hA = height(A);
assert(height(B) == wA);
const int wB = width(B);
Matrix<Tp> res(hA, std::vector<Tp>(wB));
for (int i = 0; i < hA; ++i)
for (int k = 0; k < wA; ++k)
for (int j = 0; j < wB; ++j) res[i][j] += A[i][k] * B[k][j];
return res;
}
template <typename Tp>
inline std::optional<Matrix<Tp>> mat_inv(Matrix<Tp> A) {
assert(is_square_matrix(A));
const int n = height(A);
for (int i = 0; i < n; ++i) {
A[i].resize(n * 2);
A[i][n + i] = 1;
}
for (int i = 0; i < n; ++i) {
int pivot = i;
for (; pivot < n; ++pivot)
if (A[pivot][i] != 0) break;
if (pivot == n) return {};
if (pivot != i) A[pivot].swap(A[i]);
if (A[i][i] != 1) {
const auto iv = A[i][i].inv();
for (int j = i; j < n * 2; ++j) A[i][j] *= iv;
}
for (int j = i + 1; j < n; ++j) {
const auto p = A[j][i];
if (p == 0) continue;
for (int k = i + 1; k < n * 2; ++k) A[j][k] -= p * A[i][k];
}
}
for (int i = n - 1; i > 0; --i) {
for (int j = i - 1; j >= 0; --j) {
const auto p = A[j][i];
if (p == 0) continue;
for (int k = n; k < n * 2; ++k) A[j][k] -= p * A[i][k];
}
}
for (int i = 0; i < n; ++i) A[i].erase(A[i].begin(), A[i].begin() + n);
return A;
}
template <typename Tp>
inline Tp det(Matrix<Tp> A) {
assert(is_square_matrix(A));
const int n = height(A);
Tp det = 1;
for (int i = 0; i < n; ++i) {
int pivot = i;
for (; pivot < n; ++pivot)
if (A[pivot][i] != 0) break;
if (pivot == n) return 0;
if (pivot != i) {
A[pivot].swap(A[i]);
det = -det;
}
det *= A[i][i];
const auto iv = A[i][i].inv();
for (int j = i + 1; j < n; ++j) {
const auto p = A[j][i] * iv;
if (p == 0) continue;
for (int k = i; k < n; ++k) A[j][k] -= p * A[i][k];
}
}
return det;
}
template <typename Tp>
inline Matrix<Tp> to_upper_hessenberg(Matrix<Tp> A) {
assert(is_square_matrix(A));
const int n = height(A);
for (int i = 0; i < n - 1; ++i) {
int pivot = i + 1;
for (; pivot < n; ++pivot)
if (A[pivot][i] != 0) break;
if (pivot == n) continue;
if (pivot != i + 1) {
A[pivot].swap(A[i + 1]);
for (int j = 0; j < n; ++j) std::swap(A[j][pivot], A[j][i + 1]);
}
const auto iv = A[i + 1][i].inv();
for (int j = i + 2; j < n; ++j) {
if (A[j][i] == 0) continue;
const auto v = A[j][i] * iv;
for (int k = i; k < n; ++k) A[j][k] -= v * A[i + 1][k];
for (int k = 0; k < n; ++k) A[k][i + 1] += v * A[k][j];
}
}
return A;
}
// returns det(xI - A)
template <typename Tp>
inline std::vector<Tp> charpoly(const Matrix<Tp> &A) {
const auto H = to_upper_hessenberg(A);
const int n = height(A);
std::vector<std::vector<Tp>> P(n + 1);
P[0] = {Tp(1)};
for (int i = 1; i <= n; ++i) {
P[i].resize(i + 1);
for (int j = 0; j < i; ++j) P[i][j] -= H[i - 1][i - 1] * P[i - 1][j], P[i][j + 1] += P[i - 1][j];
Tp t = 1;
for (int j = 1; j < i; ++j) {
t *= H[i - j][i - j - 1];
const auto prod = t * H[i - j - 1][i - 1];
if (prod == 0) continue;
for (int k = 0; k < i - j; ++k) P[i][k] -= prod * P[i - j - 1][k];
}
}
return P[n];
}
template <unsigned Mod>
class ModInt {
static_assert((Mod >> 31) == 0, "`Mod` must less than 2^(31)");
template <typename Int>
static std::enable_if_t<std::is_integral_v<Int>, unsigned> safe_mod(Int v) {
using D = std::common_type_t<Int, unsigned>;
return (v %= (int)Mod) < 0 ? (D)(v + (int)Mod) : (D)v;
}
struct PrivateConstructor {};
static inline PrivateConstructor private_constructor{};
ModInt(PrivateConstructor, unsigned v) : v_(v) {}
unsigned v_;
public:
static unsigned mod() { return Mod; }
static ModInt from_raw(unsigned v) { return ModInt(private_constructor, v); }
ModInt() : v_() {}
template <typename Int, typename std::enable_if_t<std::is_signed_v<Int>, int> = 0>
ModInt(Int v) : v_(safe_mod(v)) {}
template <typename Int, typename std::enable_if_t<std::is_unsigned_v<Int>, int> = 0>
ModInt(Int v) : v_(v % Mod) {}
unsigned val() const { return v_; }
ModInt operator-() const { return from_raw(v_ == 0 ? v_ : Mod - v_); }
ModInt pow(long long e) const {
if (e < 0) return inv().pow(-e);
for (ModInt x(*this), res(from_raw(1));; x *= x) {
if (e & 1) res *= x;
if ((e >>= 1) == 0) return res;
}
}
ModInt inv() const {
int x1 = 1, x3 = 0, a = val(), b = Mod;
while (b) {
int q = a / b, x1_old = x1, a_old = a;
x1 = x3, x3 = x1_old - x3 * q, a = b, b = a_old - b * q;
}
return from_raw(x1 < 0 ? x1 + (int)Mod : x1);
}
template <bool Odd = (Mod & 1)>
std::enable_if_t<Odd, ModInt> div_by_2() const {
if (v_ & 1) return from_raw((v_ + Mod) >> 1);
return from_raw(v_ >> 1);
}
ModInt &operator+=(const ModInt &a) {
if ((v_ += a.v_) >= Mod) v_ -= Mod;
return *this;
}
ModInt &operator-=(const ModInt &a) {
if ((v_ += Mod - a.v_) >= Mod) v_ -= Mod;
return *this;
}
ModInt &operator*=(const ModInt &a) {
v_ = (unsigned long long)v_ * a.v_ % Mod;
return *this;
}
ModInt &operator/=(const ModInt &a) { return *this *= a.inv(); }
friend ModInt operator+(const ModInt &a, const ModInt &b) { return ModInt(a) += b; }
friend ModInt operator-(const ModInt &a, const ModInt &b) { return ModInt(a) -= b; }
friend ModInt operator*(const ModInt &a, const ModInt &b) { return ModInt(a) *= b; }
friend ModInt operator/(const ModInt &a, const ModInt &b) { return ModInt(a) /= b; }
friend bool operator==(const ModInt &a, const ModInt &b) { return a.v_ == b.v_; }
friend bool operator!=(const ModInt &a, const ModInt &b) { return a.v_ != b.v_; }
friend std::istream &operator>>(std::istream &a, ModInt &b) {
int v;
a >> v;
b.v_ = safe_mod(v);
return a;
}
friend std::ostream &operator<<(std::ostream &a, const ModInt &b) { return a << b.val(); }
};
#line 7 "test/matrix/adjugate_matrix.0.test.cpp"
#include <array>
#include <cassert>
#include <sstream>
template <typename Tp>
inline void Dump(const Matrix<std::array<Tp, 2>> &A) {
const int h = height(A);
const int w = width(A);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
std::stringstream ss;
ss << A[i][j][0] << " + " << A[i][j][1] << "*x";
std::string s = ss.str();
s.resize(30, ' ');
std::cout << s << " \n"[j == w - 1];
}
std::cout << '\n';
}
// returns det(A0 + xA1)
template <typename Tp>
inline std::vector<Tp> det2(Matrix<std::array<Tp, 2>> A) {
assert(is_square_matrix(A));
auto sub = [](auto &a, const auto &b, Tp v, int n) {
if (v == 0) return;
for (int i = 0; i < n; ++i) a[i][0] -= v * b[i][0], a[i][1] -= v * b[i][1];
};
const int n = height(A);
Tp m = 1;
for (int i = 0; i < n; ++i) {
int pivot = i;
for (; pivot < n; ++pivot)
if (A[pivot][i][1] != 0) break;
if (pivot == n) continue;
if (pivot != i) {
A[pivot].swap(A[i]);
m = -m;
}
m *= A[i][i][1];
const auto iv = A[i][i][1].inv();
for (int j = 0; j < n; ++j) A[i][j][0] *= iv, A[i][j][1] *= iv;
for (int j = 0; j < i; ++j) sub(A[j], A[i], A[j][i][1], n);
for (int j = i + 1; j < n; ++j) sub(A[j], A[i], A[j][i][1], n);
}
// now set A = A0 + xA1, then A1 is an upper triangular matrix
int t = 0;
for (; t <= n; ++t) {
int s = 0;
for (; s < n; ++s)
if (std::all_of(A[s].begin(), A[s].end(), [](const auto &a) { return a[1] == 0; })) break;
if (s == n) break;
for (int i = 0; i < n; ++i) A[s][i][1] = std::exchange(A[s][i][0], 0);
for (int i = 0; i < s; ++i) sub(A[s], A[i], A[s][i][1], n);
for (int i = s + 1; i < n; ++i) sub(A[s], A[i], A[s][i][1], n);
if (A[s][s][1] != 0) {
m *= A[s][s][1];
const auto iv = A[s][s][1].inv();
for (int j = 0; j < n; ++j) A[s][j][0] *= iv, A[s][j][1] *= iv;
for (int i = 0; i < s; ++i) sub(A[i], A[s], A[i][s][1], n);
for (int i = s + 1; i < n; ++i) sub(A[i], A[s], A[i][s][1], n);
}
}
if (t > n) return {};
Matrix<Tp> AA(n, std::vector<Tp>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) AA[i][j] = -A[i][j][0];
auto res = charpoly(AA);
res.erase(res.begin(), res.begin() + t);
for (int i = 0; i < (int)res.size(); ++i) res[i] *= m;
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
using mint = ModInt<998244353>;
int n;
std::cin >> n;
Matrix<std::array<mint, 2>> A(n, std::vector<std::array<mint, 2>>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) std::cin >> A[i][j][0];
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) std::cin >> A[i][j][1];
const auto res = det2(A);
for (int i = 0; i < (int)res.size(); ++i) std::cout << res[i] << ' ';
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...