QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#319707#7612. Matrix Inversenhuang685Compile Error//C++208.6kb2024-02-03 04:24:432024-02-03 04:24:44

Judging History

你现在查看的是最新测评结果

  • [2024-02-03 04:24:44]
  • 评测
  • [2024-02-03 04:24:43]
  • 提交

answer

/**
 * @file qoj7612-1.cpp
 * @author n685
 * @brief
 * @date 2024-01-29
 *
 *
 */
#ifndef LOCAL
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#endif
#include <bits/stdc++.h>

#ifdef LOCAL
#include "dd/debug.h"
#else
#define dbg(...) 42
#define dbgR(...) 4242
#define dbgP(...) 420
#define dbgRP(...) 420420
void nline() {}
#endif

template <class T> std::pair<T, T> exEucl(T a, T b) {
  if (a < b) {
    // auto [x, y] = exEucl(b, a);
    T x, y;
    std::tie(x, y) = exEucl(b, a);
    return {y, x};
  }
  if (b == 0) {
    assert(a == 1);
    return {1, 0};
  }
  // auto [x, y] = exEucl(b, a % b);
  T x, y;
  std::tie(x, y) = exEucl(b, a % b);
  return {y, x - (a / b) * y};
}
template <
    class T, class U,
    typename std::enable_if<std::is_integral<U>::value, bool>::type = true>
T binpow(T a, U b) {
  // 0^0 = 1
  T res = 1;
  while (b > 0) {
    if (b % 2 == 1) {
      res *= a;
    }
    a *= a;
    b /= 2;
  }
  return res;
}

template <class Md, class V = int64_t> struct Mod {
  using T = typename std::decay<decltype(Md::value)>::type;
  T val = 0;

  template <class U> static T normalize(U val) {
    if (val <= -Md::value || Md::value <= val) {
      val %= Md::value;
    }
    if (val < 0) {
      val += Md::value;
    }
    return static_cast<T>(val);
  }

  Mod() : val(0) {}
  template <class U, typename std::enable_if<std::is_integral<U>::value,
                                             bool>::type = true>
  Mod(U _val) {
    val = normalize(_val);
  }

  // addition
  Mod &operator+=(Mod b) {
    val += b.val;
    if (val >= Md::value) {
      val -= Md::value;
    }
    return *this;
  }
  friend Mod operator+(Mod a, Mod b) { return (a += b); }
  Mod &operator++() { return (*this += 1); }
  Mod operator++(int) {
    Mod res = *this;
    ++(*this);
    return res;
  }

  // subtraction
  Mod &operator-=(Mod b) {
    val -= b.val;
    if (val < 0) {
      val += Md::value;
    }
    return *this;
  }
  friend Mod operator-(Mod a, Mod b) { return (a -= b); }
  Mod &operator--() { return (*this -= 1); }
  Mod operator--(int) {
    Mod res = *this;
    --(*this);
    return res;
  }

  // multiplication
  Mod &operator*=(Mod b) {
    val = static_cast<T>(static_cast<V>(val) * b.val % Md::value);
    return *this;
  }
  friend Mod operator*(Mod a, Mod b) { return (a *= b); }

  template <class U> Mod binpow(U b) const { return ::binpow(*this, b); }
  Mod inv() const {
    return Mod(exEucl(static_cast<V>(val), static_cast<V>(Md::value)).first);
    // return binpow(Md::value - 2);
  }

  // comparison
  bool operator==(Mod b) const { return (val == b.val); }
  //  auto operator<=>(const Mod &b) const = default;
  bool operator!=(Mod b) const { return (val != b.val); }
  bool operator<(Mod b) const { return (val < b.val); }
  bool operator>(Mod b) const { return (val > b.val); }
  bool operator<=(Mod b) const { return (val <= b.val); }
  bool operator>=(Mod b) const { return (val >= b.val); }

  // io
  friend std::istream &operator>>(std::istream &in, Mod &a) {
    V v;
    in >> v;
    a = Mod(v);
    return in;
  }
  friend std::ostream &operator<<(std::ostream &out, const Mod &a) {
    out << a.val;
    return out;
  }

  // conversion
  explicit operator T() const { return val; }
  const T &operator()() const { return val; }
  Mod operator-() const { return Mod(-val); }
};

const int MOD = (int)1e9 + 7;
using Mint = Mod<std::integral_constant<std::decay<decltype(MOD)>::type, MOD>>;

using Row = std::vector<Mint>;
Row operator+=(Row &a, Row b) {
  if (a.size() < b.size()) {
    a.resize(b.size());
  }
  for (int i = 0; i < (int)a.size(); ++i) {
    a[i] += b[i];
  }
  return a;
}
Row operator+(Row a, Row b) { return (a += b); }
Row operator-=(Row &a, Row b) {
  if (a.size() < b.size()) {
    a.resize(b.size());
  }
  for (int i = 0; i < (int)a.size(); ++i) {
    a[i] -= b[i];
  }
  return a;
}
Row operator-(Row a, Row b) { return (a -= b); }
Row operator*=(Row &a, Mint b) {
  for (int i = 0; i < (int)a.size(); ++i) {
    a[i] *= b;
  }
  return a;
}
Row operator*(Row a, Mint b) { return a *= b; }
Row operator*(Mint b, Row a) { return a *= b; }

using Mat = std::vector<Row>;
Row operator*(Mat a, Row b) {
  int n = (int)a.size();
  Row c(n);
  for (int i = 0; i < n; ++i) {
    for (int k = 0; k < n; ++k) {
      c[i] += a[i][k] * b[k];
    }
  }
  return c;
}
template <class T> auto operator*(std::vector<std::vector<T>> a, Mat b) {
  int n = (int)a.size(), m = (int)b[0].size();
  // Mat c(n, Row(m));
  std::vector c(n, std::vector<T>(m));
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      for (int k = 0; k < (int)a[0].size(); ++k) {
        c[i][j] += a[i][k] * b[k][j];
      }
    }
  }
  return c;
}

std::vector<Mint> gauss(std::vector<Row> eq) {
  if ((int)eq.size() == 0) {
    return {};
  }
  int n = (int)eq.size();
  int m = (int)eq[0].size() - 1;
  assert(n >= m);
  for (int i = 0; i < m; ++i) {
    int ind = i;
    while (ind < n && eq[ind][i] == 0) {
      ++ind;
    }
    if (ind == n) {
      std::exit(-1);
    }
    std::swap(eq[i], eq[ind]);
    eq[i] *= eq[i][i].inv();
    for (int j = 0; j < n; ++j) {
      if (j != i) {
        eq[j] -= eq[j][i] * eq[i];
      }
    }
  }
  std::vector<Mint> sol(m);
  for (int i = 0; i < m; ++i) {
    sol[i] = eq[i].back();
  }
  return sol;
}

int main() {
#ifdef LOCAL
  std::freopen("input.txt", "r", stdin);
  std::freopen("output.txt", "w", stdout);
#else
  std::cin.tie(nullptr)->sync_with_stdio(false);
#endif

  int n;
  std::cin >> n;

  std::vector a(n, std::vector<Mint>(n)), c(n, std::vector<Mint>(n));
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      std::cin >> a[i][j];
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      std::cin >> c[i][j];
    }
  }

  std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
  // std::vector<int> r(n);
  // std::iota(r.begin(), r.end(), 0);
  // std::shuffle(r.begin(), r.end(), rng);
  // r.resize(std::min(n, 20));

  std::vector<int> row, col;
  {
    Row rr(n);
    for (int i = 0; i < n; ++i) {
      rr[i] = (int)(rng() % MOD);
    }
    Row rr2 = c * (a * rr);
    for (int i = 0; i < n; ++i) {
      if (rr[i] != rr2[i]) {
        row.push_back(i);
      }
    }
  }
  {
    Mat rr(1, Row(n));
    for (int i = 0; i < n; ++i) {
      rr[0][i] = (int)(rng() % MOD);
    }
    Mat rr2 = (rr * a) * c;
    for (int i = 0; i < n; ++i) {
      if (rr[0][i] != rr2[0][i]) {
        col.push_back(i);
      }
    }
  }

  const int m = (int)row.size() * (int)col.size();
  assert((int)row.size() <= 12 && (int)col.size() <= 12);
  // std::vector val(n, std::vector(n, Row(m + 1)));
  // for (int i = 0; i < n; ++i) {
  //   for (int j = 0; j < n; ++j) {
  //     val[i][j].back() = c[i][j];
  //   }
  // }
  // for (int i = 0; i < (int)row.size(); ++i) {
  //   for (int j = 0; j < (int)col.size(); ++j) {
  //     val[row[i]][col[j]].back() = 0;
  //     val[row[i]][col[j]][(int)col.size() * i + j] = 1;
  //   }
  // }
  std::vector<Mint> sol(m);
  for (int i = 0; i < (int)row.size(); ++i) {
    std::vector<Row> eq;
    std::vector val(n, Row((int)col.size() + 1));
    for (int j = 0; j < n; ++j) {
      val[j].back() = c[row[i]][j];
    }
    for (int j = 0; j < (int)col.size(); ++j) {
      val[col[j]][j] = 1;
      val[col[j]].back() = 0;
    }
    // std::vector res = (std::vector({val}) * a)[0];
    // for (int j : col) {
    for (int j = 0; j < n; ++j) {
      Row r((int)col.size() + 1);
      for (int k = 0; k < n; ++k) {
        r += val[k] * a[k][j];
      }
      r.back() = (int)(row[i] == j) - r.back();
      for (int k = 0; k < (int)col.size(); ++k) {
        if (r[k] != 0) {
          eq.push_back(r);
          break;
        }
      }
    }
    std::vector lsol = gauss(eq);
    assert(lsol.size() == col.size());
    for (int j = 0; j < (int)col.size(); ++j) {
      sol[(int)col.size() * i + j] = lsol[j];
    }
  }
  std::vector<std::pair<std::pair<int, int>, Mint>> ans;
  for (int i = 0; i < (int)row.size(); ++i) {
    for (int j = 0; j < (int)col.size(); ++j) {
      Mint v = sol[(int)col.size() * i + j];
      if (c[row[i]][col[j]] != v) {
        ans.emplace_back(std::pair{row[i], col[j]}, v);
      }
    }
  }
  std::cout << (int)ans.size() << '\n';
  for (auto [aa, b] : ans) {
    std::cout << aa.first + 1 << ' ' << aa.second + 1 << ' ' << b << '\n';
  }
}

Details

In file included from /usr/include/c++/13/string:43,
                 from /usr/include/c++/13/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:52,
                 from answer.code:13:
/usr/include/c++/13/bits/allocator.h: In destructor ‘constexpr std::_Vector_base<Mod<std::integral_constant<int, 1000000007> >, std::allocator<Mod<std::integral_constant<int, 1000000007> > > >::_Vector_impl::~_Vector_impl()’:
/usr/include/c++/13/bits/allocator.h:184:7: error: inlining failed in call to ‘always_inline’ ‘constexpr std::allocator< <template-parameter-1-1> >::~allocator() noexcept [with _Tp = Mod<std::integral_constant<int, 1000000007> >]’: target specific option mismatch
  184 |       ~allocator() _GLIBCXX_NOTHROW { }
      |       ^
In file included from /usr/include/c++/13/vector:66,
                 from /usr/include/c++/13/functional:64,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:53:
/usr/include/c++/13/bits/stl_vector.h:133:14: note: called from here
  133 |       struct _Vector_impl
      |              ^~~~~~~~~~~~