結果

問題 No.1783 Remix Sum
ユーザー 👑 hos.lyrichos.lyric
提出日時 2021-12-12 01:08:07
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 4,888 ms / 10,000 ms
コード長 13,019 bytes
コンパイル時間 2,444 ms
コンパイル使用メモリ 137,704 KB
実行使用メモリ 16,536 KB
最終ジャッジ日時 2023-09-27 15:04:17
合計ジャッジ時間 63,715 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,592 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 2 ms
5,576 KB
testcase_04 AC 36 ms
4,376 KB
testcase_05 AC 35 ms
4,376 KB
testcase_06 AC 99 ms
5,524 KB
testcase_07 AC 465 ms
12,164 KB
testcase_08 AC 134 ms
7,652 KB
testcase_09 AC 136 ms
7,700 KB
testcase_10 AC 36 ms
4,380 KB
testcase_11 AC 36 ms
4,380 KB
testcase_12 AC 564 ms
12,244 KB
testcase_13 AC 289 ms
12,188 KB
testcase_14 AC 112 ms
7,656 KB
testcase_15 AC 477 ms
16,088 KB
testcase_16 AC 478 ms
12,244 KB
testcase_17 AC 568 ms
12,164 KB
testcase_18 AC 36 ms
4,380 KB
testcase_19 AC 156 ms
7,700 KB
testcase_20 AC 182 ms
9,836 KB
testcase_21 AC 159 ms
7,784 KB
testcase_22 AC 158 ms
7,808 KB
testcase_23 AC 215 ms
9,964 KB
testcase_24 AC 115 ms
9,760 KB
testcase_25 AC 101 ms
5,648 KB
testcase_26 AC 561 ms
12,128 KB
testcase_27 AC 96 ms
5,760 KB
testcase_28 AC 74 ms
5,708 KB
testcase_29 AC 188 ms
9,964 KB
testcase_30 AC 183 ms
9,800 KB
testcase_31 AC 156 ms
7,768 KB
testcase_32 AC 668 ms
16,016 KB
testcase_33 AC 183 ms
9,756 KB
testcase_34 AC 131 ms
10,096 KB
testcase_35 AC 291 ms
12,624 KB
testcase_36 AC 355 ms
16,256 KB
testcase_37 AC 369 ms
16,536 KB
testcase_38 AC 289 ms
12,644 KB
testcase_39 AC 127 ms
10,088 KB
testcase_40 AC 74 ms
5,868 KB
testcase_41 AC 128 ms
10,096 KB
testcase_42 AC 132 ms
10,020 KB
testcase_43 AC 295 ms
12,556 KB
testcase_44 AC 79 ms
4,376 KB
testcase_45 AC 550 ms
5,928 KB
testcase_46 AC 990 ms
7,916 KB
testcase_47 AC 1,449 ms
10,252 KB
testcase_48 AC 3,916 ms
12,624 KB
testcase_49 AC 4,728 ms
16,292 KB
testcase_50 AC 81 ms
4,380 KB
testcase_51 AC 545 ms
5,916 KB
testcase_52 AC 997 ms
8,048 KB
testcase_53 AC 1,456 ms
10,068 KB
testcase_54 AC 3,893 ms
12,640 KB
testcase_55 AC 4,750 ms
16,292 KB
testcase_56 AC 81 ms
4,380 KB
testcase_57 AC 565 ms
5,860 KB
testcase_58 AC 1,039 ms
7,984 KB
testcase_59 AC 1,698 ms
10,012 KB
testcase_60 AC 4,118 ms
12,636 KB
testcase_61 AC 4,888 ms
16,292 KB
testcase_62 AC 79 ms
4,376 KB
testcase_63 AC 552 ms
5,884 KB
testcase_64 AC 982 ms
7,868 KB
testcase_65 AC 1,458 ms
9,972 KB
testcase_66 AC 3,896 ms
12,580 KB
testcase_67 AC 20 ms
5,616 KB
testcase_68 AC 48 ms
4,376 KB
testcase_69 AC 154 ms
5,980 KB
testcase_70 AC 251 ms
7,908 KB
testcase_71 AC 356 ms
9,972 KB
testcase_72 AC 926 ms
12,640 KB
testcase_73 AC 1,108 ms
16,292 KB
testcase_74 AC 47 ms
4,376 KB
testcase_75 AC 151 ms
5,988 KB
testcase_76 AC 260 ms
7,868 KB
testcase_77 AC 193 ms
10,248 KB
testcase_78 AC 662 ms
12,556 KB
testcase_79 AC 674 ms
16,384 KB
権限があれば一括ダウンロードができます

ソースコード

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) {
  assert((int)as.size() == TEN[T]);
  if (T == 0) {
    return {as[0].pow(e)};
  }
  Mint later = 1;
  if (e >= MO) {
    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 = MO + (e - MO) % 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