結果

問題 No.1783 Remix Sum
ユーザー 👑 hos.lyrichos.lyric
提出日時 2021-12-12 01:05:21
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 12,983 bytes
コンパイル時間 2,394 ms
コンパイル使用メモリ 137,176 KB
実行使用メモリ 16,544 KB
最終ジャッジ日時 2023-09-27 15:00:03
合計ジャッジ時間 60,144 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,608 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 2 ms
5,640 KB
testcase_04 AC 40 ms
4,376 KB
testcase_05 AC 40 ms
4,376 KB
testcase_06 AC 101 ms
5,736 KB
testcase_07 AC 478 ms
12,280 KB
testcase_08 AC 143 ms
7,780 KB
testcase_09 AC 133 ms
7,696 KB
testcase_10 AC 35 ms
4,380 KB
testcase_11 AC 35 ms
4,376 KB
testcase_12 AC 574 ms
12,148 KB
testcase_13 AC 286 ms
12,252 KB
testcase_14 AC 110 ms
7,800 KB
testcase_15 AC 445 ms
16,220 KB
testcase_16 AC 466 ms
12,280 KB
testcase_17 AC 553 ms
12,252 KB
testcase_18 AC 37 ms
4,380 KB
testcase_19 AC 158 ms
7,676 KB
testcase_20 AC 185 ms
9,756 KB
testcase_21 AC 144 ms
7,816 KB
testcase_22 AC 158 ms
7,728 KB
testcase_23 AC 119 ms
9,756 KB
testcase_24 AC 119 ms
9,756 KB
testcase_25 AC 97 ms
5,724 KB
testcase_26 AC 562 ms
12,260 KB
testcase_27 AC 98 ms
5,712 KB
testcase_28 AC 75 ms
5,652 KB
testcase_29 AC 186 ms
9,752 KB
testcase_30 AC 190 ms
9,744 KB
testcase_31 AC 158 ms
7,728 KB
testcase_32 AC 672 ms
16,000 KB
testcase_33 AC 192 ms
9,756 KB
testcase_34 AC 126 ms
10,016 KB
testcase_35 AC 304 ms
12,636 KB
testcase_36 AC 366 ms
16,272 KB
testcase_37 AC 354 ms
16,384 KB
testcase_38 AC 301 ms
12,804 KB
testcase_39 AC 129 ms
9,948 KB
testcase_40 AC 74 ms
6,000 KB
testcase_41 AC 129 ms
10,016 KB
testcase_42 AC 127 ms
10,084 KB
testcase_43 AC 297 ms
12,608 KB
testcase_44 AC 77 ms
4,380 KB
testcase_45 AC 566 ms
5,960 KB
testcase_46 AC 992 ms
8,064 KB
testcase_47 AC 1,465 ms
9,992 KB
testcase_48 AC 3,930 ms
12,552 KB
testcase_49 AC 4,785 ms
16,544 KB
testcase_50 AC 80 ms
4,376 KB
testcase_51 AC 552 ms
5,856 KB
testcase_52 AC 992 ms
7,964 KB
testcase_53 AC 1,451 ms
10,012 KB
testcase_54 AC 3,917 ms
12,496 KB
testcase_55 AC 4,701 ms
16,324 KB
testcase_56 AC 82 ms
4,380 KB
testcase_57 AC 541 ms
5,964 KB
testcase_58 AC 1,021 ms
8,188 KB
testcase_59 AC 1,426 ms
9,956 KB
testcase_60 AC 3,476 ms
12,668 KB
testcase_61 AC 4,582 ms
16,316 KB
testcase_62 AC 77 ms
4,376 KB
testcase_63 AC 545 ms
6,024 KB
testcase_64 AC 995 ms
7,988 KB
testcase_65 AC 1,458 ms
10,024 KB
testcase_66 AC 3,895 ms
12,488 KB
testcase_67 AC 19 ms
5,788 KB
testcase_68 AC 47 ms
4,380 KB
testcase_69 AC 160 ms
5,856 KB
testcase_70 AC 254 ms
7,956 KB
testcase_71 AC 363 ms
10,080 KB
testcase_72 AC 933 ms
12,612 KB
testcase_73 AC 20 ms
5,784 KB
testcase_74 AC 46 ms
4,380 KB
testcase_75 AC 157 ms
5,928 KB
testcase_76 AC 259 ms
8,032 KB
testcase_77 AC 202 ms
10,012 KB
testcase_78 AC 665 ms
12,560 KB
testcase_79 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target ("avx")

#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 <map>
#include <numeric>
#include <queue>
#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> 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; }

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

////////////////////////////////////////////////////////////////////////////////
// M: prime, G: primitive root, 2^K | M - 1
template <unsigned M_, unsigned G_, int K_> struct Fft {
  static_assert(2U <= M_, "Fft: 2 <= M must hold.");
  static_assert(M_ < 1U << 30, "Fft: M < 2^30 must hold.");
  static_assert(1 <= K_, "Fft: 1 <= K must hold.");
  static_assert(K_ < 30, "Fft: K < 30 must hold.");
  static_assert(!((M_ - 1U) & ((1U << K_) - 1U)), "Fft: 2^K | M - 1 must hold.");
  static constexpr unsigned M = M_;
  static constexpr unsigned M2 = 2U * M_;
  static constexpr unsigned G = G_;
  static constexpr int K = K_;
  ModInt<M> FFT_ROOTS[K + 1], INV_FFT_ROOTS[K + 1];
  ModInt<M> FFT_RATIOS[K], INV_FFT_RATIOS[K];
  Fft() {
    const ModInt<M> g(G);
    for (int k = 0; k <= K; ++k) {
      FFT_ROOTS[k] = g.pow((M - 1U) >> k);
      INV_FFT_ROOTS[k] = FFT_ROOTS[k].inv();
    }
    for (int k = 0; k <= K - 2; ++k) {
      FFT_RATIOS[k] = -g.pow(3U * ((M - 1U) >> (k + 2)));
      INV_FFT_RATIOS[k] = FFT_RATIOS[k].inv();
    }
    assert(FFT_ROOTS[1] == M - 1U);
  }
  // as[rev(i)] <- \sum_j \zeta^(ij) as[j]
  void fft(ModInt<M> *as, int n) const {
    assert(!(n & (n - 1))); assert(1 <= n); assert(n <= 1 << K);
    int m = n;
    if (m >>= 1) {
      for (int i = 0; i < m; ++i) {
        const unsigned x = as[i + m].x;  // < M
        as[i + m].x = as[i].x + M - x;  // < 2 M
        as[i].x += x;  // < 2 M
      }
    }
    if (m >>= 1) {
      ModInt<M> prod = 1U;
      for (int h = 0, i0 = 0; i0 < n; i0 += (m << 1)) {
        for (int i = i0; i < i0 + m; ++i) {
          const unsigned x = (prod * as[i + m]).x;  // < M
          as[i + m].x = as[i].x + M - x;  // < 3 M
          as[i].x += x;  // < 3 M
        }
        prod *= FFT_RATIOS[__builtin_ctz(++h)];
      }
    }
    for (; m; ) {
      if (m >>= 1) {
        ModInt<M> prod = 1U;
        for (int h = 0, i0 = 0; i0 < n; i0 += (m << 1)) {
          for (int i = i0; i < i0 + m; ++i) {
            const unsigned x = (prod * as[i + m]).x;  // < M
            as[i + m].x = as[i].x + M - x;  // < 4 M
            as[i].x += x;  // < 4 M
          }
          prod *= FFT_RATIOS[__builtin_ctz(++h)];
        }
      }
      if (m >>= 1) {
        ModInt<M> prod = 1U;
        for (int h = 0, i0 = 0; i0 < n; i0 += (m << 1)) {
          for (int i = i0; i < i0 + m; ++i) {
            const unsigned x = (prod * as[i + m]).x;  // < M
            as[i].x = (as[i].x >= M2) ? (as[i].x - M2) : as[i].x;  // < 2 M
            as[i + m].x = as[i].x + M - x;  // < 3 M
            as[i].x += x;  // < 3 M
          }
          prod *= FFT_RATIOS[__builtin_ctz(++h)];
        }
      }
    }
    for (int i = 0; i < n; ++i) {
      as[i].x = (as[i].x >= M2) ? (as[i].x - M2) : as[i].x;  // < 2 M
      as[i].x = (as[i].x >= M) ? (as[i].x - M) : as[i].x;  // < M
    }
  }
  // as[i] <- (1/n) \sum_j \zeta^(-ij) as[rev(j)]
  void invFft(ModInt<M> *as, int n) const {
    assert(!(n & (n - 1))); assert(1 <= n); assert(n <= 1 << K);
    int m = 1;
    if (m < n >> 1) {
      ModInt<M> prod = 1U;
      for (int h = 0, i0 = 0; i0 < n; i0 += (m << 1)) {
        for (int i = i0; i < i0 + m; ++i) {
          const unsigned long long y = as[i].x + M - as[i + m].x;  // < 2 M
          as[i].x += as[i + m].x;  // < 2 M
          as[i + m].x = (prod.x * y) % M;  // < M
        }
        prod *= INV_FFT_RATIOS[__builtin_ctz(++h)];
      }
      m <<= 1;
    }
    for (; m < n >> 1; m <<= 1) {
      ModInt<M> prod = 1U;
      for (int h = 0, i0 = 0; i0 < n; i0 += (m << 1)) {
        for (int i = i0; i < i0 + (m >> 1); ++i) {
          const unsigned long long y = as[i].x + M2 - as[i + m].x;  // < 4 M
          as[i].x += as[i + m].x;  // < 4 M
          as[i].x = (as[i].x >= M2) ? (as[i].x - M2) : as[i].x;  // < 2 M
          as[i + m].x = (prod.x * y) % M;  // < M
        }
        for (int i = i0 + (m >> 1); i < i0 + m; ++i) {
          const unsigned long long y = as[i].x + M - as[i + m].x;  // < 2 M
          as[i].x += as[i + m].x;  // < 2 M
          as[i + m].x = (prod.x * y) % M;  // < M
        }
        prod *= INV_FFT_RATIOS[__builtin_ctz(++h)];
      }
    }
    if (m < n) {
      for (int i = 0; i < m; ++i) {
        const unsigned y = as[i].x + M2 - as[i + m].x;  // < 4 M
        as[i].x += as[i + m].x;  // < 4 M
        as[i + m].x = y;  // < 4 M
      }
    }
    const ModInt<M> invN = ModInt<M>(n).inv();
    for (int i = 0; i < n; ++i) {
      as[i] *= invN;
    }
  }
  void fft(vector<ModInt<M>> &as) const {
    fft(as.data(), as.size());
  }
  void invFft(vector<ModInt<M>> &as) const {
    invFft(as.data(), as.size());
  }
  vector<ModInt<M>> convolve(vector<ModInt<M>> as, vector<ModInt<M>> bs) const {
    if (as.empty() || bs.empty()) return {};
    const int len = as.size() + bs.size() - 1;
    int n = 1;
    for (; n < len; n <<= 1) {}
    as.resize(n); fft(as);
    bs.resize(n); fft(bs);
    for (int i = 0; i < n; ++i) as[i] *= bs[i];
    invFft(as);
    as.resize(len);
    return as;
  }
  vector<ModInt<M>> square(vector<ModInt<M>> as) const {
    if (as.empty()) return {};
    const int len = as.size() + as.size() - 1;
    int n = 1;
    for (; n < len; n <<= 1) {}
    as.resize(n); fft(as);
    for (int i = 0; i < n; ++i) as[i] *= as[i];
    invFft(as);
    as.resize(len);
    return as;
  }
};

constexpr unsigned MO = 120586241;
using Mint = ModInt<MO>;
const Fft<MO, 6, 20> FFT;
constexpr Mint G = 9142366;


constexpr int TEN[] = {
  1,
  10,
  100,
  1000,
  10000,
  100000,
};

int N, K, T;
Int M;
vector<int> A;

Mint GG[10][10], invGG[10][10];
void dft(vector<Mint> &as) {
  Mint work0[10], work1[10];
  for (int k = T; k < K; ++k) {
    for (int h = 0; h < TEN[K]; ++h) if (h / TEN[k] % 10 == 0) {
      for (int i = 0; i < 10; ++i) {
        work0[i] = as[h + TEN[k] * i];
      }
      for (int i = 0; i < 10; ++i) {
        work1[i] = 0;
        for (int j = 0; j < 10; ++j) {
          work1[i] += GG[i][j] * work0[j];
        }
      }
      for (int i = 0; i < 10; ++i) {
        as[h + TEN[k] * i] = work1[i];
      }
    }
  }
}
void invDft(vector<Mint> &as) {
  Mint work0[10], work1[10];
  for (int k = T; k < K; ++k) {
    for (int h = 0; h < TEN[K]; ++h) if (h / TEN[k] % 10 == 0) {
      for (int i = 0; i < 10; ++i) {
        work0[i] = as[h + TEN[k] * i];
      }
      for (int i = 0; i < 10; ++i) {
        work1[i] = 0;
        for (int j = 0; j < 10; ++j) {
          work1[i] += invGG[i][j] * work0[j];
        }
      }
      for (int i = 0; i < 10; ++i) {
        as[h + TEN[k] * i] = work1[i];
      }
    }
  }
  const Mint c = Mint(TEN[K - T]).inv();
  for (int h = 0; h < TEN[K]; ++h) {
    as[h] *= c;
  }
}

int len;
int zw[1 << 18];
vector<Mint> ei(const vector<Mint> &as, const vector<Mint> &bs) {
// cerr<<"    ei"<<endl;
// cerr<<"      as = ";pv(as.begin(),as.end());
// cerr<<"      bs = ";pv(bs.begin(),bs.end());
  static Mint f[5][1 << 18], g[5][1 << 18];
  for (int t = 0; t < T; ++t) {
    fill(f[t], f[t] + len, 0);
    fill(g[t], g[t] + len, 0);
  }
  for (int h = 0; h < TEN[T]; ++h) {
    f[zw[h]][h] += as[h];
    g[zw[h]][h] += bs[h];
  }
  for (int t = 0; t < T; ++t) {
// cerr<<"      f["<<t<<"] = ";pv(f[t],f[t]+len);
// cerr<<"      g["<<t<<"] = ";pv(g[t],g[t]+len);
    FFT.fft(f[t], len);
    FFT.fft(g[t], len);
  }
  Mint work[10];
  for (int h = 0; h < len; ++h) {
    fill(work, work + 2 * T, 0);
    for (int t = 0; t < T; ++t) for (int tt = 0; tt < T; ++tt) {
      work[t + tt] += f[t][h] * g[tt][h];
    }
    for (int t = 0; t < T; ++t) {
      f[t][h] = work[t] + work[t + T];
    }
  }
  for (int t = 0; t < T; ++t) {
    FFT.invFft(f[t], len);
  }
  vector<Mint> cs(TEN[T]);
  for (int h = 0; h < TEN[T]; ++h) {
    cs[h] = f[zw[h]][h];
  }
// cerr<<"      return ";pv(cs.begin(),cs.end());
  return cs;
}

vector<Mint> power(vector<Mint> as, Int e) {
  if (T == 0) {
    return {as[0].pow(e)};
  }
  Mint later = 1;
  if (e >= 10) {
    if (!as[0]) {
      return vector<Mint>(TEN[T], 0);
    }
    later = as[0].pow(e);
    const Mint c = as[0].inv();
    for (int h = 0; h < TEN[T]; ++h) {
      as[h] *= c;
    }
    e = 10 + (e - 10) % MO;
  }
  vector<Mint> bs(TEN[T], 0);
  bs[0] = 1;
  for (; e; e >>= 1) {
    if (e & 1) bs = ei(bs, as);
    as = ei(as, as);
  }
  for (int h = 0; h < TEN[T]; ++h) {
    bs[h] *= later;
  }
  return bs;
}

int main() {
// cerr<<G.pow(2)<<" "<<G.pow(5)<<" "<<G.pow(10)<<endl;
  for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) {
    GG[i][j] = G.pow(i * j);
    invGG[i][j] = GG[i][j].inv();
  }
  
  for (; ~scanf("%d%d%lld%d", &N, &K, &M, &T); ) {
    A.resize(N);
    for (int i = 0; i < N; ++i) {
      scanf("%d", &A[i]);
    }
    
    len = 1;
    for (; len < 2 * TEN[T]; len <<= 1) {}
    fill(zw, zw + len, 0);
    for (int h = 0; h < TEN[T]; ++h) {
      for (int t = 1; t < T; ++t) {
        zw[h] += h / TEN[t];
      }
      zw[h] %= max(T, 1);
    }
// cerr<<"len = "<<len<<endl;
// cerr<<"zw = ";pv(zw,zw+TEN[T]);
    
    vector<Mint> fs(TEN[K], 0);
    for (int i = 0; i < N; ++i) {
      fs[A[i]] += 1;
    }
    
    dft(fs);
    for (int h0 = 0; h0 < TEN[K]; h0 += TEN[T]) {
      const auto res = power(vector<Mint>(fs.begin() + h0, fs.begin() + h0 + TEN[T]), M);
      for (int i = 0; i < TEN[T]; ++i) {
        fs[h0 + i] = res[i];
      }
    }
    invDft(fs);
    
    for (int h = 0; h < TEN[K]; ++h) {
      printf("%u\n", fs[h].x);
    }
#ifdef LOCAL
cout<<"===="<<endl;
#else
break;
#endif
  }
  return 0;
}
0