QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#319736#7615. Sequence Foldingnhuang685WA 0ms3676kbC++209.2kb2024-02-03 06:22:582024-02-03 06:23:00

Judging History

This is the latest submission verdict.

  • [2024-02-03 06:23:00]
  • Judged
  • Verdict: WA
  • Time: 0ms
  • Memory: 3676kb
  • [2024-02-03 06:22:58]
  • Submitted

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;
}

const Mint ID = -45;

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);
      // return {};
      continue;
    }
    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) {
    if (i < n && eq[i][i] == 1) {
      sol[i] = eq[i].back();
    } else {
      sol[i] = ID;
    }
  }
  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);
  std::vector<int> rr(n);
  std::iota(rr.begin(), rr.end(), 0);
  std::shuffle(rr.begin(), rr.end(), rng);
  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 : rr) {
      Row r((int)col.size() + 1);
      for (int k = 0; k < n; ++k) {
        r.back() += val[k].back() * a[k][j];
      }
      for (int k = 0; k < (int)col.size(); ++k) {
        r[k] += a[col[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;
        }
      }
      // if ((int)eq.size() >= (int)col.size()) {
      //   break;
      // }
    }
    // assert((int)eq.size() == (int)col.size());
    std::vector lsol = gauss(eq);
    // assert(lsol.size() == col.size());
    for (int j = 0; j < (int)col.size(); ++j) {
      if (lsol[j] == ID) {
        sol[(int)col.size() * i + j] = a[row[i]][col[j]];
      } else {
        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

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 3676kb

input:

8 3
1 5 8

output:

17
1 1 0
1 2 0
1 3 5
2 1 750000005
2 2 406250003
3 1 250000002
3 2 718750005
4 1 0
4 2 0
5 1 0
5 2 0
6 1 0
6 2 0
7 1 0
7 2 0
8 1 0
8 2 0

result:

wrong answer 1st lines differ - expected: '2', found: '17'