QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#592884#7775. 【模板】矩阵快速幂nhuang6850 0ms0kbC++238.9kb2024-09-27 09:26:282024-09-27 09:26:28

Judging History

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

  • [2024-09-27 09:26:28]
  • 评测
  • 测评结果:0
  • 用时:0ms
  • 内存:0kb
  • [2024-09-27 09:26:28]
  • 提交

answer

/**
 * @author n685
 * @brief
 * @date 2024-09-20 21:20:01
 *
 *
 */
#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 dbg_proj(...) 420
#define dbg_rproj(...) 420420
void nline() {}
void bar() {}
void start_clock() {}
void end_clock() {}
#endif

using i128 = __int128_t;

namespace rs = std::ranges;
namespace rv = std::views;

constexpr int MOD = 998'244'353;

template <class T>
concept integral = std::integral<T> || std::is_same_v<T, i128>;

struct BigInt {
  using T = i128;
  static constexpr T BASE = 1000000000000;
  static constexpr int LG = 12;
  // std::vector<T> digits;
  std::array<T, 12> digits{};
  BigInt() = default;
  explicit BigInt(integral auto val) {
    int ind = 0;
    while (val > 0) {
      // digits.push_back(val % BASE);
      digits[ind++] = val % BASE;
      val /= BASE;
    }
  }
  explicit BigInt(std::string s) {
    // for (char c : s | rv::reverse) {
    //   digits.push_back(c - '0');
    // }
    std::reverse(s.begin(), s.end());
    s.resize((s.size() + LG - 1) / LG * LG, '0');
    int ind = -1;
    for (int i = 0; i < std::ssize(s); i += LG) {
      // digits.push_back(0);
      ++ind;
      T mul = 1;
      for (int j = 0; j < LG && i + j < std::ssize(s); ++j, mul *= 10) {
        // digits.back() += (s[i + j] - '0') * mul;
        digits[ind] += (s[i + j] - '0') * mul;
      }
    }
  }
  // void trim() {
  //   while (!digits.empty() && digits.back() == 0) {
  //     digits.pop_back();
  //   }
  // }
  void carry() {
    for (int i = 0; i < std::ssize(digits); ++i) {
      if (digits[i] < BASE) {
        continue;
      }
      // if (i == std::ssize(digits) - 1) {
      //   digits.push_back(0);
      // }
      digits[i + 1] += digits[i] / BASE;
      digits[i] %= BASE;
    }
  }
  // value needs to be nonnegative
  void deneg() {
    for (int i = 0; i < std::ssize(digits) - 1; ++i) {
      if (digits[i] >= 0) {
        continue;
      }
      T val = ((BASE - 1) - digits[i]) / BASE;
      digits[i + 1] -= val;
      digits[i] += BASE * val;
    }
    // trim();
  }
  BigInt &operator+=(const BigInt &rhs) {
    // digits.resize(std::max(digits.size(), rhs.digits.size()));
    for (int i = 0; i < std::min(std::ssize(digits), std::ssize(rhs.digits));
         ++i)
    {
      digits[i] += rhs.digits[i];
    }
    carry();
    return *this;
  }
  BigInt &operator+=(integral auto rhs) {
    // for (int i = 0; rhs > 0; ++i) {
    //   if (i == std::ssize(digits)) {
    //     digits.push_back(rhs % BASE);
    //   } else {
    //     digits[i] += rhs % BASE;
    //   }
    //   rhs /= BASE;
    // }
    // if (digits.empty()) {
    //   digits.push_back(0);
    // }
    digits[0] += rhs;
    carry();
    return *this;
  }
  BigInt &operator-=(const BigInt &rhs) {
    assert(digits.size() >= rhs.digits.size());
    for (int i = 0; i < std::ssize(rhs.digits); ++i) {
      digits[i] -= rhs.digits[i];
    }
    deneg();
    return *this;
  }
  BigInt &operator-=(integral auto rhs) {
    for (int i = 0; rhs > 0; ++i) {
      digits[i] -= rhs % BASE;
      rhs /= BASE;
    }
    deneg();
    return *this;
  }
  BigInt operator*(const BigInt &rhs) {
    if (digits.empty() || rhs.digits.empty()) {
      return BigInt{};
    }
    BigInt ans;
    // ans.digits.resize(digits.size() + rhs.digits.size() - 1);
    for (int i = 0; i < std::ssize(digits); ++i) {
      for (int j = 0; j < std::ssize(rhs.digits); ++j) {
        ans.digits[i + j] += digits[i] * rhs.digits[j];
      }
    }
    ans.carry();
    // ans.trim();
    return ans;
  }
  BigInt &operator*=(integral auto rhs) {
    for (T &i : digits) {
      i *= rhs;
    }
    return *this;
  }
  std::pair<BigInt, int> div(int rhs) const {
    BigInt ans;
    T rem = 0;
    int ind = 0;
    for (T i : digits | rv::reverse) {
      rem = rem * BASE + i;
      // ans.digits.push_back(rem / rhs);
      ans.digits[ind++] = rem / rhs;
      rem %= rhs;
    }
    rs::reverse(ans.digits);
    return {ans, static_cast<int>(rem)};
  }
  int operator%(int rhs) const {
    int val = 0;
    for (T i : digits | rv::reverse) {
      val
        = static_cast<int>((static_cast<int64_t>(val) * BASE % rhs + i) % rhs);
    }
    return val;
  }
  bool operator==(const BigInt &rhs) const = default;
  bool operator!=(const BigInt &rhs) const = default;
  auto operator<=>(const BigInt &rhs) const {
    if (digits.size() != rhs.digits.size()) {
      return digits.size() <=> rhs.digits.size();
    }
    for (int i = static_cast<int>(digits.size()) - 1; i >= 0; --i) {
      if (digits[i] != rhs.digits[i]) {
        return digits[i] <=> rhs.digits[i];
      }
    }
    return std::strong_ordering::equal;
  }
};
BigInt operator+(BigInt a, const BigInt &b) { return a += b; }
BigInt operator+(BigInt a, integral auto b) { return a += b; }
BigInt operator-(BigInt a, const BigInt &b) { return a -= b; }
BigInt operator-(BigInt a, integral auto b) { return a -= b; }
BigInt operator*(BigInt a, integral auto b) { return a *= b; }

template <class T> constexpr T INF = T{};
template <std::floating_point T>
constexpr T INF<T> = std::numeric_limits<T>::infinity();
template <> constexpr int INF<int> = 0x3f3f3f3f; // 1061109567
template <>
constexpr int64_t INF<int64_t> = 0x3f3f3f3f3f3f3f3f; // 4557430888798830399
template <>
constexpr i128 INF<i128> = (static_cast<i128>(INF<int64_t>) << 64)
  | INF<int64_t>; // 84069761239290679208598432424319205183

struct Edge {
  int u, v;
  i128 w;
};

clock_t tot = 0;
clock_t tot2 = 0;
clock_t tot3 = 0;

void solve() {
  static_assert(integral<i128>);
  int n, m;
  std::string sk;
  std::cin >> n >> m >> sk;
  BigInt k(sk);

  std::vector<Edge> edges(m);
  for (auto &[u, v, w] : edges) {
    int64_t ww;
    std::cin >> u >> v >> ww;
    --u;
    --v;
    w = ww;
  }

  auto start2 = clock();
  std::vector dist(n + 1, std::vector(n, std::vector<i128>(n, INF<i128>)));
  std::vector d0(2 * n * n + 1, std::vector<i128>(n, INF<i128>));
  d0[0][0] = 0;
  for (int i = 0; i < n; ++i) {
    dist[0][i][i] = 0;
  }
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j < n; ++j) {
      for (auto &[u, v, w] : edges) {
        dist[i][j][v] = std::min(dist[i][j][v], dist[i - 1][j][u] + w);
      }
    }
    d0[i] = dist[i][0];
  }
  for (int i = n + 1; i <= 2 * n * n; ++i) {
    for (auto &[u, v, w] : edges) {
      d0[i][v] = std::min(d0[i][v], d0[i - 1][u] + w);
    }
  }
  tot2 += clock() - start2;
  if (k <= BigInt{2 * n * n}) {
    int kk = std::stoi(sk);
    for (int i = 0; i < n; ++i) {
      if (d0[kk][i] == INF<i128>) {
        std::cout << "-1 ";
      } else {
        std::cout << static_cast<int>(d0[kk][i] % MOD) << ' ';
      }
    }
    std::cout << '\n';
    return;
  }

  auto start3 = clock();
  std::vector dp(n * n + 1, std::vector<BigInt>(n));
  std::vector isinf(n * n + 1, std::vector<bool>(n, true));
  for (int i = 0; i < n; ++i) {
    i128 mi = INF<i128> / n;
    int sz = 1;
    for (int j = 1; j <= n; ++j) {
      if (dist[j][i][i] != INF<i128> && dist[j][i][i] * sz < mi * j) {
        mi = dist[j][i][i];
        sz = j;
      }
    }
    if (mi == INF<i128> / n) {
      continue;
    }
    for (int j = n * n - n; j <= n * n; ++j) {
      if (d0[j][i] == INF<i128>) {
        continue;
      }
      auto [times, rem] = (k - (j + n * n)).div(sz);
      int rest = n * n;
      if (rem > 0) {
        times += 1;
        rest -= sz - rem;
      }
      BigInt res = times * mi + d0[j][i];
      if (isinf[rest][i]) {
        dp[rest][i] = res;
      } else {
        dp[rest][i] = std::min(dp[rest][i], res);
      }
      isinf[rest][i] = false;
    }
  }
  tot3 += clock() - start3;
  auto start = clock();
  std::vector<std::tuple<int, int, BigInt>> edges2;
  edges2.reserve(edges.size());
  for (auto [u, v, w] : edges) {
    edges2.emplace_back(u, v, w);
  }
  for (int i = n * n - 1; i >= 0; --i) {
    for (const auto &[u, v, w] : edges2) {
      if (!isinf[i + 1][u]) {
        if (isinf[i][v]) {
          dp[i][v] = dp[i + 1][u] + w;
        } else {
          dp[i][v] = std::min(dp[i][v], dp[i + 1][u] + w);
        }
        isinf[i][v] = false;
      }
    }
  }
  tot += clock() - start;
  for (int i = 0; i < n; ++i) {
    if (isinf[0][i]) {
      std::cout << "-1 ";
    } else {
      std::cout << dp[0][i] % MOD << ' ';
    }
  }
  std::cout << '\n';
}

int main() {
#ifndef LOCAL
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
#endif
  std::freopen("input.txt", "r", stdin);

  int s, t;
  std::cin >> s >> t;
  start_clock();
  for (int i = 0; i < t; ++i) {
    // dbg(i + 1);
    solve();
    // bar();
  }
  end_clock();
  dbg(tot2);
  dbg(tot3);
  dbg(tot);
}

详细

Subtask #1:

score: 0
Runtime Error

Test #1:

score: 0
Runtime Error

input:

1
1
100 101 899539897889989959
74 35 910832669819965536
35 85 910832669819965536
85 88 910832669819965536
88 30 910832669819965536
30 58 910832669819965536
58 60 910832669819965536
60 34 910832669819965536
34 8 910832669819965536
8 67 910832669819965536
67 89 910832669819965536
89 32 910832669819965...

output:


result:


Subtask #2:

score: 0
Runtime Error

Test #7:

score: 0
Runtime Error

input:

2
1
300 598 8179377797889487867988994778539839593376697796496698959964978969
1 2 977880533270721156
2 1 977880533270721156
2 3 977880533270721156
3 2 977880533270721156
3 4 977880533270721156
4 3 977880533270721156
4 5 977880533270721156
5 4 977880533270721156
5 6 977880533270721156
6 5 977880533270...

output:


result:


Subtask #3:

score: 0
Skipped

Dependency #2:

0%

Subtask #4:

score: 0
Skipped

Dependency #1:

0%

Subtask #5:

score: 0
Skipped

Dependency #1:

0%

Subtask #6:

score: 0
Skipped

Dependency #3:

0%