Submission #73376492


Source Code Expand

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <chrono>
#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 T> ostream &operator<<(ostream &os, const vector<T> &as);
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 {};
  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;
}


// [l, r)^n
template <class F> void doArraysRec(int n, int l, int r, F f, int i, vector<int> &as) {
  if (i == n) {
    f(as);
  } else {
    for (as[i] = l; as[i] < r; ++as[i]) doArraysRec(n, l, r, f, i + 1, as);
  }
}
template <class F> void doArrays(int n, int l, int r, F f) {
  vector<int> as(n);
  doArraysRec(n, l, r, f, 0, as);
}


template <class String>
vector<pair<int, int>> lyndonSuffix(const String &as) {
  const int n = as.size();
  vector<pair<int, int>> pqs(n + 1);
  pqs[0] = make_pair(0, 0);
  for (int u = 0; u < n; ) {
    for (int p = 1, q = 1, r = 0, v = u + 1; ; ++v) {
      // as[u, v) = as[u, u + p)^q as[u, u + r)
      // as[u, u + p): Lyndon
      pqs[v] = (r != 0) ? pqs[u + r] : make_pair(p, q);
      if (v == n || as[v - p] > as[v]) {
        u = v - r;
        break;
      } else if (as[v - p] < as[v]) {
        p = v + 1 - u; q = 1; r = 0;
      } else {
        if (++r == p) { ++q; r = 0; }
      }
    }
  }
  return pqs;
}


/*
  c(i) = A[0,i) b A[i,N)
  
  for i < j,
  cmp(c(i), c(j))
  = cmp(b A[i,j), A[i,j) b)
  = cmp(b^INF, A[i,j)^INF)
  
  c(0) <= c(1), ..., c(N)   <=>  b^INF <= \min[0<j<=N] A[0,j)^INF
  c(0), ..., c(N-1) > c(N)  <=>  b^INF >  \max[0<=i<N] A[i,N)^INF
  
  j: minimize A[0,j)^INF
    tie-break min j
  Claim. c(1), ..., c(j-1) is not opt.
    assume:
      0 < i < j
      c(0) > c(i)
      c(i) <= c(j)
    b^INF > A[0,j)^INF
    b^INF <= A[i,j)^INF
    A[0,j)^INF < A[i,j)^INF
    A[0,j)^INF < A[0,i)^INF
    (st)^INF < s^INF
    (st)^INF < t^INF
    sts < sst
    stt < tst
    ts < st
    st < ts
    contradiction
  
  i: maximize A[i,N)^INF
    tie-break: max i
  Claim. c(i+1), ..., c(N-1) is not opt.
    assume:
      i < j < N
      c(i) > c(j)
      c(i) <= c(N)
    b^INF > A[i,j)^INF
    b^INF <= A[i,N)^INF
    A[i,j)^INF < A[i,N)^INF
    A[j,N)^INF < A[i,N)^INF
    s^INF < (st)^INF
    t^INF < (st)^INF
    sst < sts
    tst < stt
    st < ts
    ts < ts
    contradiction  
  
  Claim. equivalent to minimizing (-A)[i,N)
    take i: minimize (-A)[i,N)
    want to prove (-A)[i,N)^INF <= (-A)[j,N)^INF
    only hard case: (-A)[i,N) is prefix of (-A)[j,N)
    j < i < N
    (-A)[i,N) = s
    (-A)[j,N) = st
    s^INF <= (st)^INF  <=>  sst <= sts  <=>  st <= ts  <=>  s^INF <= t^INF
    induct on j
  
  counting problem:
    for each A[l,r) in the decomposition
    count b s.t.
      1 <= |b| <= M
      b^INF > A[l,r)^INF
  
  a := A[l,r)
  Case. |b| < |a|
    Case. LCP(b, a) < |b|
      condition: b > a[0, |b|)
    Case. LCP(b, a) = |b|
      always b^INF > a^INF by the decomposition
  Case. |b| >= |a|
    Case. LCP(b, a) < |a|
      condition: b[0, |a|) > a
    Case. LCP(b, a) >= |a|
      b = as
      (as)^INF > a^INF  <=>  asa > aas  <=>  sa > as  <=>  s^INF > a^INF
      reduced to |b|-|a|
*/

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

int main() {
//  getCutsStress(); return 0;
  
  for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
    scanf("%d%lld%lld", &N, &M, &K);
    A.resize(N);
    for (int i = 0; i < N; ++i) scanf("%lld", &A[i]);
    
    vector<Int> negA(N);
    for (int i = 0; i < N; ++i) negA[i] = -A[i];
    const auto pqs = lyndonSuffix(negA);
    vector<int> cuts{N};
    for (int i = N; i > 0; ) {
      const int p = pqs[i].first;
      const int q = pqs[i].second;
      for (int j = q; --j >= 0; ) cuts.push_back(i -= p);
    }
    reverse(cuts.begin(), cuts.end());
    const int len = (int)cuts.size() - 1;
//cerr<<"cuts = "<<cuts<<endl;
    
    vector<Mint> ways(len, 0);
    for (int h = 0; h < len; ++h) {
      const int l = cuts[h], r = cuts[h + 1];
      const int m = r - l;
      vector<Mint> fs(m + 1, 0);
      for (int i = 0; i < m; ++i) fs[i + 1] = fs[i] * K + (K - A[l + i]);
//cerr<<vector<Int>(A.begin()+l,A.begin()+r)<<": "<<fs<<endl;
      for (int i = 0; i < m && i <= M; ++i) {
        // |b| = i, m+i, 2m+i, ...  <= M
        constexpr int LEN = 10;
        vector<Mint> gs(LEN);
        gs[0] = fs[i] + (i ? 1 : 0);
        for (int j = 1; j < LEN; ++j) gs[j] = fs[m] * Mint(K).pow((j-1) * m + i) + gs[j - 1];
        for (int j = 1; j < LEN; ++j) gs[j] += gs[j - 1];
//cerr<<"  "<<i<<": "<<gs<<endl;
        const auto cs = findLinearRecurrence(gs);
        ways[h] += linearRecurrenceAt(gs, cs, (M - i) / m);
      }
    }
//cerr<<"ways = "<<ways<<endl;
    
    Mint all;
    {
      Mint k = K;
      all = (k == 1) ? M : ((k.pow(M+1) - k) / (k - 1));
    }
    vector<Mint> ans(N + 1, 0);
    for (int h = 0; h <= len; ++h) {
      ans[cuts[h]] = ((h == 0) ? all : ways[h - 1]) - ((h == len) ? 0 : ways[h]);
    }
    for (int i = 0; i <= N; ++i) {
      if (i) printf(" ");
      printf("%u", ans[i].x);
    }
    puts("");
  }
#ifndef LOCAL
  break;
#endif
  }
  return 0;
}

Submission Info

Submission Time
Task C - Addictive Addition
User hos_lyric
Language C++ IOI-Style(GNU++20) (GCC 14.2.0)
Score 100
Code Size 10664 Byte
Status AC
Exec Time 1307 ms
Memory 23120 KiB

Compile Error

Main.cpp: In function ‘int main()’:
Main.cpp:278:10: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  278 |     scanf("%d%lld%lld", &N, &M, &K);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:280:38: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
  280 |     for (int i = 0; i < N; ++i) scanf("%lld", &A[i]);
      |                                 ~~~~~^~~~~~~~~~~~~~~

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 100 / 100
Status
AC × 1
AC × 91
Set Name Test Cases
Sample example_00.txt
All example_00.txt, test_00.txt, test_01.txt, test_02.txt, test_03.txt, test_04.txt, test_05.txt, test_06.txt, test_07.txt, test_08.txt, test_09.txt, test_10.txt, test_11.txt, test_12.txt, test_13.txt, test_14.txt, test_15.txt, test_16.txt, test_17.txt, test_18.txt, test_19.txt, test_20.txt, test_21.txt, test_22.txt, test_23.txt, test_24.txt, test_25.txt, test_26.txt, test_27.txt, test_28.txt, test_29.txt, test_30.txt, test_31.txt, test_32.txt, test_33.txt, test_34.txt, test_35.txt, test_36.txt, test_37.txt, test_38.txt, test_39.txt, test_40.txt, test_41.txt, test_42.txt, test_43.txt, test_44.txt, test_45.txt, test_46.txt, test_47.txt, test_48.txt, test_49.txt, test_50.txt, test_51.txt, test_52.txt, test_53.txt, test_54.txt, test_55.txt, test_56.txt, test_57.txt, test_58.txt, test_59.txt, test_60.txt, test_61.txt, test_62.txt, test_63.txt, test_64.txt, test_65.txt, test_66.txt, test_67.txt, test_68.txt, test_69.txt, test_70.txt, test_71.txt, test_72.txt, test_73.txt, test_74.txt, test_75.txt, test_76.txt, test_77.txt, test_78.txt, test_79.txt, test_80.txt, test_81.txt, test_82.txt, test_83.txt, test_84.txt, test_85.txt, test_86.txt, test_87.txt, test_88.txt, test_89.txt
Case Name Status Exec Time Memory
example_00.txt AC 0 ms 1708 KiB
test_00.txt AC 396 ms 7184 KiB
test_01.txt AC 310 ms 4560 KiB
test_02.txt AC 292 ms 3484 KiB
test_03.txt AC 239 ms 2508 KiB
test_04.txt AC 283 ms 2736 KiB
test_05.txt AC 156 ms 1708 KiB
test_06.txt AC 68 ms 1708 KiB
test_07.txt AC 259 ms 2232 KiB
test_08.txt AC 260 ms 2248 KiB
test_09.txt AC 259 ms 2216 KiB
test_10.txt AC 348 ms 3764 KiB
test_11.txt AC 349 ms 3772 KiB
test_12.txt AC 348 ms 3784 KiB
test_13.txt AC 1141 ms 3744 KiB
test_14.txt AC 1168 ms 3756 KiB
test_15.txt AC 1145 ms 3824 KiB
test_16.txt AC 1064 ms 3740 KiB
test_17.txt AC 1060 ms 3756 KiB
test_18.txt AC 1078 ms 3756 KiB
test_19.txt AC 938 ms 15500 KiB
test_20.txt AC 918 ms 15628 KiB
test_21.txt AC 932 ms 15440 KiB
test_22.txt AC 930 ms 15492 KiB
test_23.txt AC 917 ms 15892 KiB
test_24.txt AC 1169 ms 23120 KiB
test_25.txt AC 1141 ms 23120 KiB
test_26.txt AC 1152 ms 23116 KiB
test_27.txt AC 1307 ms 23112 KiB
test_28.txt AC 1302 ms 23112 KiB
test_29.txt AC 1296 ms 22868 KiB
test_30.txt AC 875 ms 15416 KiB
test_31.txt AC 751 ms 15420 KiB
test_32.txt AC 964 ms 15416 KiB
test_33.txt AC 769 ms 15420 KiB
test_34.txt AC 793 ms 15416 KiB
test_35.txt AC 1001 ms 15504 KiB
test_36.txt AC 985 ms 15488 KiB
test_37.txt AC 969 ms 15548 KiB
test_38.txt AC 712 ms 15468 KiB
test_39.txt AC 1000 ms 15424 KiB
test_40.txt AC 753 ms 15428 KiB
test_41.txt AC 1070 ms 20304 KiB
test_42.txt AC 969 ms 16048 KiB
test_43.txt AC 982 ms 15500 KiB
test_44.txt AC 897 ms 15540 KiB
test_45.txt AC 1000 ms 15520 KiB
test_46.txt AC 881 ms 15420 KiB
test_47.txt AC 943 ms 15416 KiB
test_48.txt AC 978 ms 15416 KiB
test_49.txt AC 755 ms 15416 KiB
test_50.txt AC 929 ms 15420 KiB
test_51.txt AC 1069 ms 23116 KiB
test_52.txt AC 1183 ms 17496 KiB
test_53.txt AC 1182 ms 15660 KiB
test_54.txt AC 1094 ms 15404 KiB
test_55.txt AC 928 ms 15404 KiB
test_56.txt AC 1038 ms 19392 KiB
test_57.txt AC 1067 ms 19388 KiB
test_58.txt AC 1094 ms 19380 KiB
test_59.txt AC 1007 ms 19392 KiB
test_60.txt AC 1084 ms 19392 KiB
test_61.txt AC 1067 ms 19392 KiB
test_62.txt AC 1091 ms 19396 KiB
test_63.txt AC 1019 ms 19392 KiB
test_64.txt AC 1088 ms 19392 KiB
test_65.txt AC 1040 ms 19392 KiB
test_66.txt AC 931 ms 15416 KiB
test_67.txt AC 882 ms 15420 KiB
test_68.txt AC 971 ms 15420 KiB
test_69.txt AC 897 ms 15420 KiB
test_70.txt AC 894 ms 15420 KiB
test_71.txt AC 1125 ms 19468 KiB
test_72.txt AC 1110 ms 19388 KiB
test_73.txt AC 983 ms 19392 KiB
test_74.txt AC 1176 ms 19396 KiB
test_75.txt AC 1126 ms 19388 KiB
test_76.txt AC 962 ms 16564 KiB
test_77.txt AC 969 ms 16160 KiB
test_78.txt AC 1059 ms 15532 KiB
test_79.txt AC 1043 ms 15404 KiB
test_80.txt AC 1181 ms 15532 KiB
test_81.txt AC 930 ms 15548 KiB
test_82.txt AC 944 ms 15580 KiB
test_83.txt AC 801 ms 15420 KiB
test_84.txt AC 872 ms 15672 KiB
test_85.txt AC 965 ms 15548 KiB
test_86.txt AC 969 ms 15936 KiB
test_87.txt AC 932 ms 16376 KiB
test_88.txt AC 880 ms 15644 KiB
test_89.txt AC 998 ms 15388 KiB