QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#641924#6161. 作业题Elegia100 ✓3ms5000kbC++148.5kb2024-10-15 03:19:562024-10-15 03:19:56

Judging History

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

  • [2024-10-15 03:19:56]
  • 评测
  • 测评结果:100
  • 用时:3ms
  • 内存:5000kb
  • [2024-10-15 03:19:56]
  • 提交

answer

#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <valarray>
#include <random>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<class T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &x : v)
    is >> x;
  return is;
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  if (!v.empty()) {
    os << v.front();
    for (int i = 1; i < v.size(); ++i)
      os << ' ' << v[i];
  }
  return os;
}

const uint Mod = 998244353;

constexpr uint norm(uint v) { return v >= Mod ? v - Mod : v; }

struct Z {
  uint v;

  constexpr Z(uint v = 0) : v(v) {}

  inline constexpr Z operator+(const Z &rhs) const { return norm(v + rhs.v); }

  inline constexpr Z operator-(const Z &rhs) const { return norm(v + Mod - rhs.v); }

  inline constexpr Z operator-() const { return norm(Mod - v); }

  inline constexpr Z operator*(const Z &rhs) const { return static_cast<ull>(v) * rhs.v % Mod; }

  inline constexpr Z inv() const;

  inline constexpr Z operator/(const Z &rhs) const { return *this * rhs.inv(); }

  constexpr operator uint() const { return v; }
};

inline constexpr Z &operator+=(Z &lhs, const Z &rhs) { return lhs = lhs + rhs; }

inline constexpr Z &operator-=(Z &lhs, const Z &rhs) { return lhs = lhs - rhs; }

inline constexpr Z &operator*=(Z &lhs, const Z &rhs) { return lhs = lhs * rhs; }

inline constexpr Z &operator/=(Z &lhs, const Z &rhs) { return lhs = lhs / rhs; }

inline constexpr Z pow(Z base, uint exp) {
  Z res = 1;
  for (; exp; base *= base, exp >>= 1)
    if (exp & 1)
      res *= base;
  return res;
}

inline constexpr Z Z::inv() const { return pow(*this, Mod - 2); }

const int N = 30, M = 500, W = 153005;

static uniform_int_distribution<> uid0(0, (int) Mod), uid1(1, (int) Mod);

struct Trunc {
  Z a, b;

  Trunc() {}

  Trunc(Z a, Z b) : a(a), b(b) {}

  Trunc operator+(const Trunc &rhs) const { return Trunc(a + rhs.a, b + rhs.b); }

  Trunc operator-(const Trunc &rhs) const { return Trunc(a - rhs.a, b - rhs.b); }

  Trunc operator-() const { return Trunc(-a, -b); }

  Trunc operator*(const Trunc &rhs) const {
    return Trunc(a * rhs.a, Z((static_cast<ull>(b.v) * rhs.a.v + static_cast<ull>(a.v) * rhs.b.v) % Mod));
  }

  int deg() const {
    if (a.v) return 0;
    if (b.v) return 1;
    return 2;
  }

  Trunc shift(int d) const {
    if (d == 0) return *this;
    return Trunc(0, a);
  }

  Trunc inv() const {
    Trunc nv = Trunc();
    nv.a = a.inv();
    nv.b = -b * nv.a * nv.a;
    return nv;
  }

  template<class URNG>
  static Trunc rand(URNG &g) {
    return Trunc({Z(uid1(g)), Z(uid0(g))});
  }
};

inline Trunc &operator+=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs + rhs; }

inline Trunc &operator-=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs - rhs; }

inline Trunc &operator*=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs * rhs; }

int n, m;
int u[M], v[M], w[M];
int edc[W], phi[W];

int f[N];

int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }

int tries;

const int LIMIT = 30;
int act;

namespace Kirkhoff {

  int adj[N][N];
  Trunc mat[N][N];

  // works when #SpanningTrees % p != 0
  vector<Trunc> BM(const vector<Trunc> &a) {
    vector<Trunc> rec = {Trunc({Z(1), Z(0)})}, crec = {Trunc({Z(1), Z(0)})};
    int l = 0;
    for (int r = 1; r <= a.size(); ++r) {
      Trunc v = Trunc();
      for (int i = 0; i < rec.size(); ++i) v += rec[i] * a[r - 1 - i];
      crec.insert(crec.begin(), Trunc());
      if (v.deg() < 2) {
        assert(v.deg() == 0);
        vector<Trunc> t = rec;
        if (crec.size() > t.size()) t.resize(crec.size());
        for (int i = 0; i < crec.size(); ++i)
          t[i] -= v * crec[i];
        if (l * 2 <= r - 1) {
          crec = rec;
          Trunc nv = v.inv();
          for (int i = 0; i < crec.size(); ++i)
            crec[i] *= nv;
          l = r - l;
        }
        swap(rec, t);
      }
    }
    return rec;
  }

  Trunc diag[N], row[N], col[N];
  int si[N * N], sj[N * N];
  Trunc sw[N * N];

  Trunc sparseDet(int n) {
    ++act;
    while (true) {
      ++tries;
      Trunc val = Trunc({Z(1), Z(0)});
      for (int i = 0; i < n; ++i) {
        diag[i] = Trunc::rand(rng);
        val *= diag[i];
        row[i] = Trunc::rand(rng);
        col[i] = Trunc::rand(rng);
      }
      int tot = 0;
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
          if (mat[i][j].deg() == 0) {
            si[tot] = i;
            sj[tot] = j;
            sw[tot] = mat[i][j] * diag[i];
            ++tot;
          }
      vector<Trunc> vec;
      for (int i = 0; i <= n * 2; ++i) {
        static Trunc tmp[N];
        fill(tmp, tmp + n, Trunc());
        for (int j = 0; j < tot; ++j)
          tmp[sj[j]] += row[si[j]] * sw[j];
        vec.push_back(inner_product(tmp, tmp + n, col, Trunc()));
        //cerr << vec.back().a << ' ' << vec.back().b << " | ";
        copy(tmp, tmp + n, row);
      }
      //cerr << '\n';
      auto rec = BM(vec);
      //cerr << rec.size() << '\n';
      if (rec.size() == n + 1) {
        Trunc eigen = rec.back();
        if (n & 1) eigen = -eigen;
        return eigen * val.inv();
      }
    }
  }

  Trunc det(int n) {
    Trunc ret = Trunc({Z(1), Z(0)});
    for (int i = 0; i < n; ++i) {
      int lowest = mat[i][i].deg(), pref = i;
      for (int j = i + 1; j < n; ++j) {
        if (lowest > mat[i][j].deg()) {
          lowest = mat[i][j].deg();
          pref = j;
        }
      }
      if (pref != i) {
        for (int j = i; j < n; ++j)
          swap(mat[i][j], mat[pref][j]);
        ret = -ret;
      }
      if (lowest + ret.deg() >= 2) return Trunc();
      ret *= mat[i][i];
      Trunc nv = Trunc();
      if (lowest == 0) {
        nv = mat[i][i].inv();
      } else
        nv.a = mat[i][i].b.inv();
      for (int j = i; j < n; ++j)
        mat[i][j] *= nv;
      for (int j = i + 1; j < n; ++j)
        for (int k = n - 1; k >= i; --k)
          mat[j][k] -= (mat[i][k] * mat[j][i]).shift(mat[j][i].deg() - lowest);
    }
    return ret;
  }

  Z solve() {
    for (int i = 0; i < n; ++i)
      fill(mat[i], mat[i] + n, Trunc());
    int cnt = 0;
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j)
        if (adj[i][j]) {
          Trunc e = Trunc({Z(1), Z(adj[i][j])});
          mat[i][i] += e;
          mat[j][j] += e;
          mat[i][j] -= e;
          mat[j][i] -= e;
          ++cnt;
        }
    Z ret = (cnt >= LIMIT ? det(n - 1) : sparseDet(n - 1)).b;
    return ret;
  }

}

unordered_map<bitset<M>, Z> memo;

int main() {
#ifdef ELEGIA
  freopen("test.in", "r", stdin);
  int nol_cl = clock();
#endif
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    cin >> u[i] >> v[i] >> w[i];
    --u[i];
    --v[i];
    ++edc[w[i]];
  }
  iota(phi, phi + W, 0);
  Z ans = 0;
  int cnt = 0;
  for (int i = 1; i < W; ++i) {
    for (int j = i + i; j < W; j += i) {
      edc[i] += edc[j];
      phi[j] -= phi[i];
    }
    if (edc[i] < n - 1) continue;
    iota(f, f + n, 0);
    memset(Kirkhoff::adj, 0, sizeof(Kirkhoff::adj));
    int con = n;
    static bitset<M> edv;
    edv.reset();
    for (int j = 0; j < m; ++j)
      if (w[j] % i == 0) {
        edv.set(j);
        Kirkhoff::adj[u[j]][v[j]] = w[j];
        int x = find(u[j]), y = find(v[j]);
        if (x != y) {
          --con;
          f[y] = x;
        }
      }
    if (con != 1) continue;
    auto it = memo.find(edv);
    if (it != memo.end()) {
      ans += it->second * Z(phi[i]);
      continue;
    }
    ++cnt;
    Z th = Kirkhoff::solve();
    ans += th * Z(phi[i]);
    memo.insert(make_pair(edv, th));
  }
  cerr << "total dets: " << cnt << '\n';
  cerr << "average attempts: " << (double)tries / act << '\n';
  cout << ans << '\n';

#ifdef ELEGIA
  LOG("Time: %dms\n", int ((clock()
          -nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
  return 0;
}

詳細信息


Pretests


Final Tests

Test #1:

score: 10
Accepted
time: 3ms
memory: 5000kb

input:

5 10
1 2 113400
1 3 131040
1 4 131040
1 5 126000
2 3 131040
2 4 90720
2 5 138600
3 4 110880
3 5 110880
4 5 95760

output:

549298858

result:

ok 1 number(s): "549298858"

Test #2:

score: 10
Accepted
time: 3ms
memory: 4852kb

input:

6 15
1 2 110880
1 3 141120
1 4 141120
1 5 131040
1 6 151200
2 3 137280
2 4 105840
2 5 138600
2 6 150480
3 4 138600
3 5 131040
3 6 137280
4 5 85680
4 6 151200
5 6 131040

output:

627752274

result:

ok 1 number(s): "627752274"

Test #3:

score: 10
Accepted
time: 3ms
memory: 4904kb

input:

25 24
1 2 147840
1 3 98280
2 4 120960
3 5 128520
5 6 128520
6 7 143640
1 8 138600
7 9 131040
3 10 147840
10 11 120120
5 12 120120
4 13 131040
8 14 151200
13 15 151200
5 16 110880
11 17 120960
6 18 151200
6 19 147840
5 20 147840
1 21 120960
14 22 110880
13 23 120120
18 24 98280
1 25 131040

output:

623404094

result:

ok 1 number(s): "623404094"

Test #4:

score: 10
Accepted
time: 3ms
memory: 4840kb

input:

28 28
1 2 128520
2 3 98280
1 4 138600
4 5 98280
2 6 98280
1 7 131040
3 8 138600
2 9 147840
6 10 120120
1 11 120960
7 12 138600
6 13 147840
3 14 120960
6 15 120960
9 16 120120
4 17 143640
3 18 128520
15 19 147840
9 20 120120
6 21 120960
20 22 147840
10 23 131040
5 24 138600
7 25 143640
5 26 120960
4 ...

output:

640377458

result:

ok 1 number(s): "640377458"

Test #5:

score: 10
Accepted
time: 0ms
memory: 4704kb

input:

30 30
1 2 110880
1 3 120960
3 4 131040
3 5 120120
3 6 138600
5 7 98280
3 8 120960
5 9 128520
1 10 128520
2 11 138600
5 12 98280
10 13 98280
11 14 143640
3 15 120960
10 16 98280
16 17 138600
5 18 138600
13 19 147840
18 20 120960
13 21 131040
15 22 151200
22 23 131040
2 24 128520
6 25 120960
20 26 138...

output:

309797364

result:

ok 1 number(s): "309797364"

Test #6:

score: 10
Accepted
time: 3ms
memory: 4796kb

input:

25 25
1 2 131040
2 3 120120
2 4 98280
3 5 110880
5 6 120120
4 7 120960
1 8 128520
4 9 110880
3 10 147840
7 11 120960
4 12 120960
2 13 138600
8 14 120960
1 15 128520
8 16 131040
10 17 110880
14 18 98280
9 19 131040
7 20 147840
8 21 138600
14 22 138600
5 23 151200
7 24 131040
13 25 143640
12 1 143640

output:

302382070

result:

ok 1 number(s): "302382070"

Test #7:

score: 10
Accepted
time: 3ms
memory: 4828kb

input:

28 376
1 2 152501
1 3 152501
1 4 152501
1 5 152501
1 6 152501
1 7 152501
1 8 152501
1 9 152501
1 10 152501
1 11 152501
1 12 152501
1 13 152501
1 14 152501
1 15 152501
1 16 152501
1 17 152501
1 18 152501
1 19 152501
1 20 152501
1 21 152501
1 22 152501
1 23 152501
1 24 152501
1 25 152501
1 26 152501
1...

output:

493255263

result:

ok 1 number(s): "493255263"

Test #8:

score: 10
Accepted
time: 3ms
memory: 4792kb

input:

30 431
1 2 152501
1 3 152501
1 4 152501
1 5 152501
1 6 152501
1 7 152501
1 8 152501
1 9 152501
1 10 152501
1 11 152501
1 12 152501
1 13 152501
1 14 152501
1 15 152501
1 16 152501
1 17 152501
1 18 152501
1 19 152501
1 20 152501
1 21 152501
1 22 152501
1 23 152501
1 24 152501
1 25 152501
1 26 152501
1...

output:

441996120

result:

ok 1 number(s): "441996120"

Test #9:

score: 10
Accepted
time: 3ms
memory: 4700kb

input:

28 372
1 2 152501
1 3 152501
1 4 152501
1 5 152501
1 6 152501
1 7 152501
1 8 152501
1 9 152501
1 10 152501
1 11 152501
1 12 152501
1 13 152501
1 14 152501
1 15 152501
1 16 152501
1 17 152501
1 18 152501
1 19 152501
1 20 152501
1 21 152501
1 22 152501
1 23 152501
1 24 152501
1 25 152501
1 26 152501
1...

output:

179882346

result:

ok 1 number(s): "179882346"

Test #10:

score: 10
Accepted
time: 3ms
memory: 4804kb

input:

30 432
1 2 152501
1 3 152501
1 4 152501
1 5 152501
1 6 152501
1 7 152501
1 8 152501
1 9 152501
1 10 152501
1 11 152501
1 12 152501
1 13 152501
1 14 152501
1 15 152501
1 16 152501
1 17 152501
1 18 152501
1 19 152501
1 20 152501
1 21 152501
1 22 152501
1 23 152501
1 24 152501
1 25 152501
1 26 152501
1...

output:

45748263

result:

ok 1 number(s): "45748263"

Extra Test:

score: 0
Extra Test Passed