QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#317409#8173. T Tile Placement Countinghos_lyricAC ✓2221ms6476kbC++148.3kb2024-01-28 23:32:362024-01-28 23:32:37

Judging History

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

  • [2024-01-28 23:32:37]
  • 评测
  • 测评结果:AC
  • 用时:2221ms
  • 内存:6476kb
  • [2024-01-28 23:32:36]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")

////////////////////////////////////////////////////////////////////////////////
template <unsigned M_> struct ModInt {
  static constexpr unsigned M = M_;
  unsigned x;
  constexpr ModInt() : x(0U) {}
  constexpr ModInt(unsigned x_) : x(x_ % M) {}
  constexpr ModInt(unsigned long long x_) : x(x_ % M) {}
  constexpr ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
  constexpr ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
  ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
  ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
  ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
  ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
  ModInt pow(long long e) const {
    if (e < 0) return inv().pow(-e);
    ModInt a = *this, b = 1U; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
  }
  ModInt inv() const {
    unsigned a = M, b = x; int y = 0, z = 1;
    for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
    assert(a == 1U); return ModInt(y);
  }
  ModInt operator+() const { return *this; }
  ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0U; return a; }
  ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
  ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
  ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
  ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
  template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
  template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
  template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
  template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
  explicit operator bool() const { return x; }
  bool operator==(const ModInt &a) const { return (x == a.x); }
  bool operator!=(const ModInt &a) const { return (x != a.x); }
  friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
////////////////////////////////////////////////////////////////////////////////

constexpr unsigned MO = 998244353;
using Mint = ModInt<MO>;

vector<Mint> findLinearRecurrence(const vector<Mint> &as) {
  const int n = as.size();
  int d = 0, m = 0;
  vector<Mint> cs(n + 1, 0), bs(n + 1, 0);
  cs[0] = bs[0] = 1;
  Mint invBef = 1;
  for (int i = 0; i < n; ++i) {
    ++m;
    Mint dif = as[i];
    for (int j = 1; j < d + 1; ++j) dif += cs[j] * as[i - j];
    if (dif.x != 0) {
      auto csDup = cs;
      const Mint r = dif * invBef;
      for (int j = m; j < n; ++j) cs[j] -= r * bs[j - m];
      if (2 * d <= i) {
        d = i + 1 - d;
        m = 0;
        bs = csDup;
        invBef = dif.inv();
      }
    }
  }
  cs.resize(d + 1);
  return cs;
}

// x^e mod rev(cs)
vector<Mint> powerRev(const vector<Mint> &cs, Int e) {
  assert(!cs.empty());
  assert(cs[0] == 1);
  const int d = (int)cs.size() - 1;
  if (d == 0) {
    return {};
  } else if (d == 1) {
    return {(-cs[1]).pow(e)};
  }
  auto mul = [&](const vector<Mint> &fs, const vector<Mint> &gs) {
    vector<Mint> hs(d + d - 1, 0);
    for (int i = 0; i < d; ++i) for (int j = 0; j < d; ++j) {
      hs[i + j] += fs[i] * gs[j];
    }
    for (int i = d + d - 1; --i >= d; ) {
      for (int j = 1; j <= d; ++j) {
        hs[i - j] -= cs[j] * hs[i];
      }
    }
    hs.resize(d);
    return hs;
  };
  vector<Mint> xs(d, 0), ys(d, 0);
  xs[1] = 1;
  ys[0] = 1;
  for (; ; xs = mul(xs, xs)) {
    if (e & 1) ys = mul(ys, xs);
    if (!(e >>= 1)) break;
  }
  return ys;
}

Mint linearRecurrenceAt(const vector<Mint> &as, const vector<Mint> &cs, Int e) {
  assert(!cs.empty());
  assert(cs[0] == 1);
  const int d = (int)cs.size() - 1;
  assert((int)as.size() >= d);
  const auto fs = powerRev(cs, e);
  Mint ans = 0;
  for (int i = 0; i < d; ++i) {
    ans += fs[i] * as[i];
  }
  return ans;
}


vector<int> uf;
int root(int u) {
  return (uf[u] < 0) ? u : (uf[u] = root(uf[u]));
}
bool connect(int u, int v) {
  u = root(u);
  v = root(v);
  if (u == v) return false;
  if (uf[u] > uf[v]) swap(u, v);
  uf[u] += uf[v];
  uf[v] = u;
  return true;
}


// const int LEN = 2000;
const int LEN = 500;
int U;
map<vector<int>, int> ids;
vector<vector<int>> seqs;
void dfs(int N, int y, int k, vector<int> &seq) {
  if (y == N) {
    seqs.push_back(seq);
    ids[seq] = U++;
  } else {
    for (int a = 0; a <= k; ++a) {
      seq[y] = a;
      dfs(N, y + 1, (a == k) ? (k + 1) : k, seq);
    }
  }
}
pair<vector<Mint>, vector<Mint>> mendou(int N) {
  const Mint A = 2, B = Mint(4).inv();
  U = 0;
  ids.clear();
  seqs.clear();
  {
    vector<int> seq(N);
    dfs(N, 0, 0, seq);
  }
cerr<<"[mendou] N = "<<N<<", U = "<<U<<endl;
  
  vector<vector<Mint>> mat(U, vector<Mint>(U, 0));
  vector<Mint> crt(U, 0);
  for (int u = 0; u < U; ++u) {
    for (int p = 0; p < 1 << N; ++p) for (int q = 0; q < 1 << (N-1); ++q) {
      uf.assign(N + N, -1);
      for (int y = 0; y < N; ++y) {
        for (int yy = 0; yy < y; ++yy) if (seqs[u][yy] == seqs[u][y]) {
          connect(yy, y);
          break;
        }
      }
      Mint wt = 1;
      for (int y = 0; y < N; ++y) if (p >> y & 1) {
        wt *= A;
        if (connect(y, N + y)) wt *= B;
      }
      for (int y = 0; y < N - 1; ++y) if (q >> y & 1) {
        wt *= A;
        if (connect(N + y, N + y + 1)) wt *= B;
      }
      int k = 0;
      vector<int> seq(N, -1);
      for (int y = 0; y < N; ++y) {
        for (int yy = 0; yy < y; ++yy) if (root(N + yy) == root(N + y)) {
          seq[y] = seq[yy];
          break;
        }
        if (!~seq[y]) {
          seq[y] = k++;
        }
      }
      auto it = ids.find(seq);
      assert(it != ids.end());
      const int v = it->second;
      mat[u][v] += wt;
      if (!u && !p) {
        crt[v] += wt;
      }
    }
  }
// cerr<<"hello "<<__LINE__<<endl;
  
  vector<Mint> as(LEN, 0);
  for (int m = 1; m < LEN; ++m) {
    for (int u = 0; u < U; ++u) as[m] += crt[u];
    as[m] *= Mint(2).pow(N * m);
    
    vector<Mint> nxt(U, 0);
    for (int u = 0; u < U; ++u) for (int v = 0; v < U; ++v) {
      nxt[v] += crt[u] * mat[u][v];
    }
    crt.swap(nxt);
  }
  const auto cs = findLinearRecurrence(as);
// cerr<<as<<" "<<cs<<endl;
cerr<<"|cs| = "<<cs.size()<<endl;
  
  return make_pair(as, cs);
}

int main() {
  // for (int N = 1; N <= 7; ++N) mendou(N);
  
  Int N, M;
  for (; ~scanf("%lld%lld", &N, &M); ) {
    Mint ans = 0;
    if (N % 4 == 0 && M % 4 == 0) {
      N /= 4;
      M /= 4;
      const auto res = mendou(N);
      ans = linearRecurrenceAt(res.first, res.second, M);
    }
    printf("%u\n", ans.x);
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3808kb

input:

4 4

output:

2

result:

ok "2"

Test #2:

score: 0
Accepted
time: 0ms
memory: 4068kb

input:

2 8

output:

0

result:

ok "0"

Test #3:

score: 0
Accepted
time: 1ms
memory: 3808kb

input:

12 3456

output:

491051233

result:

ok "491051233"

Test #4:

score: 0
Accepted
time: 0ms
memory: 3804kb

input:

1 1

output:

0

result:

ok "0"

Test #5:

score: 0
Accepted
time: 0ms
memory: 3872kb

input:

20 999999999999999983

output:

0

result:

ok "0"

Test #6:

score: 0
Accepted
time: 0ms
memory: 4076kb

input:

24 999999999999999994

output:

0

result:

ok "0"

Test #7:

score: 0
Accepted
time: 0ms
memory: 4000kb

input:

24 999999999999999955

output:

0

result:

ok "0"

Test #8:

score: 0
Accepted
time: 2210ms
memory: 6416kb

input:

28 999999999999999928

output:

846645622

result:

ok "846645622"

Test #9:

score: 0
Accepted
time: 0ms
memory: 3788kb

input:

28 999999999999999971

output:

0

result:

ok "0"

Test #10:

score: 0
Accepted
time: 0ms
memory: 3800kb

input:

28 999999999999999901

output:

0

result:

ok "0"

Test #11:

score: 0
Accepted
time: 0ms
memory: 3804kb

input:

28 999999999999999945

output:

0

result:

ok "0"

Test #12:

score: 0
Accepted
time: 0ms
memory: 4036kb

input:

30 1000000000000000000

output:

0

result:

ok "0"

Test #13:

score: 0
Accepted
time: 1ms
memory: 4092kb

input:

4 144115188075855868

output:

479168365

result:

ok "479168365"

Test #14:

score: 0
Accepted
time: 0ms
memory: 3820kb

input:

4 288230376151711740

output:

661413713

result:

ok "661413713"

Test #15:

score: 0
Accepted
time: 0ms
memory: 3808kb

input:

4 576460752303423484

output:

854857972

result:

ok "854857972"

Test #16:

score: 0
Accepted
time: 0ms
memory: 3744kb

input:

8 144115188075855868

output:

266363233

result:

ok "266363233"

Test #17:

score: 0
Accepted
time: 1ms
memory: 4072kb

input:

8 288230376151711740

output:

862901307

result:

ok "862901307"

Test #18:

score: 0
Accepted
time: 1ms
memory: 3872kb

input:

8 576460752303423484

output:

455991900

result:

ok "455991900"

Test #19:

score: 0
Accepted
time: 1ms
memory: 3792kb

input:

12 144115188075855868

output:

226857121

result:

ok "226857121"

Test #20:

score: 0
Accepted
time: 1ms
memory: 3800kb

input:

12 288230376151711740

output:

717445399

result:

ok "717445399"

Test #21:

score: 0
Accepted
time: 1ms
memory: 4076kb

input:

12 576460752303423484

output:

935277864

result:

ok "935277864"

Test #22:

score: 0
Accepted
time: 1ms
memory: 3820kb

input:

16 144115188075855868

output:

631950327

result:

ok "631950327"

Test #23:

score: 0
Accepted
time: 1ms
memory: 3884kb

input:

16 288230376151711740

output:

73767413

result:

ok "73767413"

Test #24:

score: 0
Accepted
time: 1ms
memory: 3812kb

input:

16 576460752303423484

output:

329402693

result:

ok "329402693"

Test #25:

score: 0
Accepted
time: 7ms
memory: 3900kb

input:

20 144115188075855868

output:

125405814

result:

ok "125405814"

Test #26:

score: 0
Accepted
time: 7ms
memory: 3896kb

input:

20 288230376151711740

output:

794579293

result:

ok "794579293"

Test #27:

score: 0
Accepted
time: 7ms
memory: 3832kb

input:

20 576460752303423484

output:

726571847

result:

ok "726571847"

Test #28:

score: 0
Accepted
time: 108ms
memory: 4288kb

input:

24 144115188075855868

output:

310529292

result:

ok "310529292"

Test #29:

score: 0
Accepted
time: 109ms
memory: 4000kb

input:

24 288230376151711740

output:

493789216

result:

ok "493789216"

Test #30:

score: 0
Accepted
time: 109ms
memory: 4016kb

input:

24 576460752303423484

output:

606221157

result:

ok "606221157"

Test #31:

score: 0
Accepted
time: 2206ms
memory: 6416kb

input:

28 144115188075855868

output:

964541053

result:

ok "964541053"

Test #32:

score: 0
Accepted
time: 2212ms
memory: 6400kb

input:

28 288230376151711740

output:

42971353

result:

ok "42971353"

Test #33:

score: 0
Accepted
time: 2210ms
memory: 6476kb

input:

28 576460752303423484

output:

179569141

result:

ok "179569141"

Test #34:

score: 0
Accepted
time: 0ms
memory: 3796kb

input:

6 5

output:

0

result:

ok "0"

Test #35:

score: 0
Accepted
time: 1ms
memory: 3800kb

input:

14 28

output:

0

result:

ok "0"

Test #36:

score: 0
Accepted
time: 0ms
memory: 3816kb

input:

25 6365

output:

0

result:

ok "0"

Test #37:

score: 0
Accepted
time: 1ms
memory: 3800kb

input:

18 529543996

output:

0

result:

ok "0"

Test #38:

score: 0
Accepted
time: 0ms
memory: 3796kb

input:

10 675199829716849556

output:

0

result:

ok "0"

Test #39:

score: 0
Accepted
time: 7ms
memory: 4116kb

input:

20 425279816112802872

output:

269059955

result:

ok "269059955"

Test #40:

score: 0
Accepted
time: 1ms
memory: 3808kb

input:

8 38212554426330756

output:

207344318

result:

ok "207344318"

Test #41:

score: 0
Accepted
time: 105ms
memory: 4028kb

input:

24 666881067086698696

output:

245351821

result:

ok "245351821"

Test #42:

score: 0
Accepted
time: 0ms
memory: 3820kb

input:

4 728683474913510792

output:

466882081

result:

ok "466882081"

Test #43:

score: 0
Accepted
time: 2221ms
memory: 6392kb

input:

28 201838304882525604

output:

217184228

result:

ok "217184228"

Test #44:

score: 0
Accepted
time: 0ms
memory: 3768kb

input:

4 8560

output:

596875387

result:

ok "596875387"

Test #45:

score: 0
Accepted
time: 1ms
memory: 3764kb

input:

12 60764

output:

930662011

result:

ok "930662011"

Test #46:

score: 0
Accepted
time: 0ms
memory: 4076kb

input:

8 45272

output:

239612337

result:

ok "239612337"

Test #47:

score: 0
Accepted
time: 1ms
memory: 3804kb

input:

8 84616

output:

826857610

result:

ok "826857610"

Test #48:

score: 0
Accepted
time: 0ms
memory: 3824kb

input:

4 316408

output:

529567983

result:

ok "529567983"

Test #49:

score: 0
Accepted
time: 0ms
memory: 4044kb

input:

8 12

output:

1182

result:

ok "1182"

Test #50:

score: 0
Accepted
time: 1ms
memory: 3804kb

input:

8 16

output:

16644

result:

ok "16644"

Test #51:

score: 0
Accepted
time: 0ms
memory: 4072kb

input:

4 8

output:

6

result:

ok "6"

Test #52:

score: 0
Accepted
time: 0ms
memory: 3796kb

input:

12 16

output:

5253822

result:

ok "5253822"

Extra Test:

score: 0
Extra Test Passed