QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#678775#9526. Subsequence Countingucup-team087#TL 0ms4060kbC++1411.5kb2024-10-26 16:06:392024-10-26 16:06:41

Judging History

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

  • [2024-10-26 16:06:41]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:4060kb
  • [2024-10-26 16:06:39]
  • 提交

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


// T: monoid representing information of an interval.
//   T()  should return the identity.
//   T(S s)  should represent a single element of the array.
//   T::pull(const T &l, const T &r)  should pull two intervals.
template <class T> struct SegmentTreePoint {
  int logN, n;
  vector<T> ts;
  SegmentTreePoint() : logN(0), n(0) {}
  explicit SegmentTreePoint(int n_) {
    for (logN = 0, n = 1; n < n_; ++logN, n <<= 1) {}
    ts.resize(n << 1);
  }
  template <class S> explicit SegmentTreePoint(const vector<S> &ss) {
    const int n_ = ss.size();
    for (logN = 0, n = 1; n < n_; ++logN, n <<= 1) {}
    ts.resize(n << 1);
    for (int i = 0; i < n_; ++i) at(i) = T(ss[i]);
    build();
  }
  T &at(int i) {
    return ts[n + i];
  }
  void build() {
    for (int u = n; --u; ) pull(u);
  }

  inline void pull(int u) {
    ts[u].pull(ts[u << 1], ts[u << 1 | 1]);
  }

  // Changes the value of point a to s.
  template <class S> void change(int a, const S &s) {
    assert(0 <= a); assert(a < n);
    ts[a += n] = T(s);
    for (; a >>= 1; ) pull(a);
  }

  // Applies T::f(args...) to point a.
  template <class F, class... Args>
  void ch(int a, F f, Args &&... args) {
    assert(0 <= a); assert(a < n);
    (ts[a += n].*f)(args...);
    for (; a >>= 1; ) pull(a);
  }

  // Calculates the product for [a, b).
  T get(int a, int b) {
    assert(0 <= a); assert(a <= b); assert(b <= n);
    if (a == b) return T();
    T prodL, prodR, t;
    for (a += n, b += n; a < b; a >>= 1, b >>= 1) {
      if (a & 1) { t.pull(prodL, ts[a++]); prodL = t; }
      if (b & 1) { t.pull(ts[--b], prodR); prodR = t; }
    }
    t.pull(prodL, prodR);
    return t;
  }

  // Calculates T::f(args...) of a monoid type for [a, b).
  //   op(-, -)  should calculate the product.
  //   e()  should return the identity.
  template <class Op, class E, class F, class... Args>
#if __cplusplus >= 201402L
  auto
#else
  decltype((std::declval<T>().*F())())
#endif
  get(int a, int b, Op op, E e, F f, Args &&... args) {
    assert(0 <= a); assert(a <= b); assert(b <= n);
    if (a == b) return e();
    auto prodL = e(), prodR = e();
    for (a += n, b += n; a < b; a >>= 1, b >>= 1) {
      if (a & 1) prodL = op(prodL, (ts[a++].*f)(args...));
      if (b & 1) prodR = op((ts[--b].*f)(args...), prodR);
    }
    return op(prodL, prodR);
  }

  // Find min b s.t. T::f(args...) returns true,
  // when called for the partition of [a, b) from left to right.
  //   Returns n + 1 if there is no such b.
  template <class F, class... Args>
  int findRight(int a, F f, Args &&... args) {
    assert(0 <= a); assert(a <= n);
    if ((T().*f)(args...)) return a;
    if (a == n) return n + 1;
    a += n;
    for (; ; a >>= 1) if (a & 1) {
      if ((ts[a].*f)(args...)) {
        for (; a < n; ) {
          if (!(ts[a <<= 1].*f)(args...)) ++a;
        }
        return a - n + 1;
      }
      ++a;
      if (!(a & (a - 1))) return n + 1;
    }
  }

  // Find max a s.t. T::f(args...) returns true,
  // when called for the partition of [a, b) from right to left.
  //   Returns -1 if there is no such a.
  template <class F, class... Args>
  int findLeft(int b, F f, Args &&... args) {
    assert(0 <= b); assert(b <= n);
    if ((T().*f)(args...)) return b;
    if (b == 0) return -1;
    b += n;
    for (; ; b >>= 1) if ((b & 1) || b == 2) {
      if ((ts[b - 1].*f)(args...)) {
        for (; b <= n; ) {
          if (!(ts[(b <<= 1) - 1].*f)(args...)) --b;
        }
        return b - n - 1;
      }
      --b;
      if (!(b & (b - 1))) return -1;
    }
  }
};  // SegmentTreePoint<T>

////////////////////////////////////////////////////////////////////////////////


// a x + b y = (+/-) gcd(a, b)
//   (a, 0): g = a, x = 1, y = 0
//   (0, b), (b, b), (-b, b) (b != 0): g = b, x = 0, y = 1
//   otherwise: 2 |x| <= |b|, 2 |y| <= |a|
// S: signed integer
template <class S> S gojo(S a, S b, S &x, S &y) {
  if (b != 0) {
    const S g = gojo(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
  } else {
    x = 1;
    y = 0;
    return a;
  }
}

// floor(a / b)
Int divFloor(Int a, Int b) {
  return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}

// ceil(a / b)
Int divCeil(Int a, Int b) {
  return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}


int TLen;
vector<int> T;

struct Node {
// string str;
  Mint a[11][11];
  Node() : a{} {
// str="";
    for (int u = 0; u <= TLen; ++u) a[u][u] = 1;
  }
  Node(int t) : a{} {
// str=".";for(int u=0;u<TLen;++u)if(T[u]==t){str=(char)('0'+u);break;}
    for (int u = 0; u <= TLen; ++u) a[u][u] = 1;
    for (int u = 0; u < TLen; ++u) if (T[u] == t) a[u][u + 1] = 1;
  }
  void pull(const Node &l, const Node &r) {
// str=l.str+r.str;
    unsigned long long b[11][11] = {};
    for (int u = 0; u <= TLen; ++u) for (int w = u; w <= TLen; ++w) for (int v = w; v <= TLen; ++v) b[u][v] += (unsigned long long)l.a[u][w].x * r.a[w][v].x;
    for (int u = 0; u <= TLen; ++u) for (int v = 0; v <= TLen; ++v) a[u][v] = b[u][v];
  }
};
Node operator*(const Node &a, const Node &b) {
  Node c;
  c.pull(a, b);
  return c;
}
Node power(Node a, int e) {
  Node b;
  for (; ; a = a * a) {
    if (e & 1) b = b * a;
    if (!(e >>= 1)) return b;
  }
}


Node solve(int step, const vector<int> &xs, const vector<Node> &fs) {
  const int len = fs.size();
cerr<<xs.back()<<" "<<step<<": len = "<<len<<endl;
assert(len<=2100);
// cerr<<"[solve] step = "<<step<<", xs = "<<xs<<", fs = ";for(int i=0;i<len;++i)cerr<<fs[i].str<<" ";cerr<<endl;
  assert((int)xs.size() == len + 1);
  if (step <= 1) {
    Node ret;
    for (int i = 0; i < len; ++i) {
      ret = ret * power(fs[i], xs[i + 1] - xs[i]);
    }
    return ret;
  }
  
  SegmentTreePoint<Node> seg(len);
  // (x, (pos, val))
  vector<pair<int, pair<int, int>>> events;
  for (int i = 0; i < len; ++i) {
    const int l = xs[i], r = xs[i + 1];
    // l <= x + step y < r
    vector<int> ys{0, step, l % step, r % step};
    sort(ys.begin(), ys.end());
    ys.erase(unique(ys.begin(), ys.end()), ys.end());
    for (int j = 0; j < (int)ys.size() - 1; ++j) {
      const int y = ys[j];
      const int e = divCeil(r - y, step) - divCeil(l - y, step);
// cerr<<l<<" "<<r<<"; "<<ys[j]<<" "<<ys[j+1]<<": "<<e<<endl;
      if (j == 0) {
        seg.at(i) = power(fs[i], e);
      } else {
        events.emplace_back(ys[j], make_pair(i, e));
      }
    }
  }
  seg.build();
  sort(events.begin(), events.end());
  events.emplace_back(step, make_pair(-1, 0));
  vector<int> xxs;
  vector<Node> ffs;
  int x = 0;
  for (const auto &ev : events) {
    if (x < ev.first) {
// cerr<<x<<" "<<seg.ts[1].str<<endl;
      xxs.push_back(x);
      ffs.push_back(seg.ts[1]);
      x = ev.first;
    }
    const int i = ev.second.first;
    const int e = ev.second.second;
    if (~i) {
      seg.change(i, power(fs[i], e));
    }
  }
  xxs.push_back(step);
  return solve(divCeil(xs.back(), step) * step - xs.back(), xxs, ffs);
}

int N, K, L;
vector<int> F, V;

int main() {
  for (; ~scanf("%d%d%d%d", &N, &TLen, &K, &L); ) {
    T.resize(TLen);
    for (int u = 0; u < TLen; ++u) {
      scanf("%d", &T[u]);
    }
    F.resize(N);
    V.resize(N);
    for (int i = 0; i < N; ++i) {
      scanf("%d%d", &F[i], &V[i]);
    }
    
    int D;
    {
      int x, y;
      gojo(K, L, x, y);
      D = (x % L + L) % L;
    }
cerr<<"D = "<<D<<endl;
    
    vector<int> xs(N + 1, 0);
    vector<Node> fs(N);
    for (int i = 0; i < N; ++i) {
      xs[i + 1] = xs[i] + F[i];
      fs[i] = Node(V[i]);
    }
    
    const Node ans = solve(D, xs, fs);
// cerr<<ans.str<<endl;
    printf("%u\n", ans.a[0][TLen].x);
#ifndef LOCAL
break;
#endif
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

4 2 17 27
3 1
10 3
6 1
10 3
1 1

output:

76

result:

ok single line: '76'

Test #2:

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

input:

5 3 1789 15150
555 718 726
72 555
1029 718
5807 726
1002 718
7240 555

output:

390415327

result:

ok single line: '390415327'

Test #3:

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

input:

1 1 1 1000000000
1000
1000000000 1000

output:

1755647

result:

ok single line: '1755647'

Test #4:

score: -100
Time Limit Exceeded

input:

1999 10 999999999 1000000000
944 901 986 915 979 988 947 999 969 946
198832 985
235662 982
367137 938
219700 949
166086 906
488084 905
891250 984
243743 971
253382 987
181971 935
2382 948
462701 981
4681 925
113363 916
119397 921
337742 982
427128 921
285959 986
197975 978
140753 907
167150 974
4576...

output:


result: