QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#765605#8049. Equal Sumslizhu6TL 0ms3812kbC++2013.4kb2024-11-20 14:47:552024-11-20 14:47:55

Judging History

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

  • [2024-11-20 14:47:55]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:3812kb
  • [2024-11-20 14:47:55]
  • 提交

answer

#pragma GCC optimize("-Ofast")

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cassert>
#include <numeric>

using namespace std;

typedef long long LL;
constexpr int N = 1010;
constexpr int mod = 998244353;
template <typename Tp1, typename Tp2> inline void cmax(Tp1 &A, const Tp2 &B)  { if (A < B) A = B; return; }
template <typename Tp1, typename Tp2> inline void cmin(Tp1 &A, const Tp2 &B)  { if (A > B) A = B; return; }
template <typename Tp1, typename Tp2, int mod = ::mod> inline void ad(Tp1 &A, const Tp2 &B) { A = (A + B) % mod; return; }
template <typename Tp1, typename Tp2, int mod = ::mod> inline void sb(Tp1 &A, const Tp2 &B) { A = (A + mod - B) % mod; return; }

int n, m;

struct par
{
  par() = default;
  par(int _x, int _y) : x(_x), y(_y) { }
  bool operator<(const par Q) const { return x != Q.x ? x < Q.x : y < Q.y; }
  bool operator==(const par Q) const { return x == Q.x && y == Q.y; }
  bool operator>(const par Q) const { return x != Q.x ? x > Q.x : y > Q.y; }
  int x, y;
} lx[N], ly[N];

struct poly
{
  typedef poly this_type;
  static constexpr int mod = 998244353;
  static constexpr int ebase = 119;
  std::vector<long long> poly_base;

  static constexpr int qp[] = { 15311432, 267099868,
    733596141, 565042129, 363395222, 996173970, 24514907,
    629671588, 968855178, 666702199, 350007156, 63912897,
    584193783, 258648936, 166035806, 476477967, 781712469,
    922799308, 452798380, 929031873, 372528824, 911660635,
    998244352, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  static constexpr int qpinv[] = { 469870224, 382752275,
    428961804, 950391366, 704923114, 121392023, 3707709,
    283043518, 708402881, 814576206, 358024708, 129292727,
    335559352, 381598368, 685443576, 304459705, 135236158,
    609441965, 87557064, 337190230, 509520358, 86583718,
    998244352, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

  static long long builtin_quick_pow(
      long long base, long long ind)
  {
    LL res = 1;
    while (ind)
    {
      if (ind & 1ll)
        res = res * base % mod;
      ind >>= 1;
      base = base * base % mod;
    }
    return res;
  }
  inline long long& operator[](const std::size_t pos)
  {
    return poly_base[pos];
  }
  auto at(const std::size_t pos)
  {
    return poly_base.at(pos);
  }
  inline const long long& operator[](
      const std::size_t pos) const
  {
    return poly_base[pos];
  }
  inline long long get(const std::size_t pos) const noexcept
  {
    return pos < poly_base.size() ? poly_base[pos] : 0;
  }

  void del_zero()
  {
    while (!poly_base.back())
      poly_base.pop_back();
  }

  poly() = default;

  poly(std::initializer_list<long long> _list)
      : poly_base(_list)
  {
    std::reverse(poly_base.begin(), poly_base.end());
    while (!poly_base.back())
      poly_base.pop_back();
  }
  poly(std::vector<long long> _vec)
      : poly_base(std::move(_vec))
  {
  }
  explicit poly(int _siz, LL _val = 0)
      : poly_base(
            std::move(std::vector<long long>(_siz, _val)))
  {
  }
  // size() - 1 is the poly's highest index
  inline std::size_t size() const
  {
    return poly_base.size();
  }
  inline void resize(std::size_t new_size, LL new_val = LL())
  {
    return poly_base.resize(new_size, new_val);
  }
  inline bool empty() const { return poly_base.empty(); }

  poly operator+(const this_type& Q) const
  {
    poly res;
    res.poly_base.resize(std::max(this->size(), Q.size()));
    for (std::size_t i = 0; i != size(); i++)
      (res.operator[](i) += operator[](i)) %= mod;
    for (std::size_t i = 0; i != Q.size(); i++)
      (res.operator[](i) += Q[i]) %= mod;
    return res;
  }
  poly& operator+=(const this_type& Q)
  {
    poly_base.resize(std::max(this->size(), Q.size()));
    for (std::size_t i = 0; i != Q.size(); i++)
      (this->operator[](i) += Q[i]) %= mod;
    return *this;
  }
  poly operator-(const this_type& Q) const
  {
    poly res;
    res.poly_base.resize(std::max(this->size(), Q.size()));
    for (std::size_t i = 0; i != size(); i++)
      (res.operator[](i) += operator[](i)) %= mod;
    for (std::size_t i = 0; i != Q.size(); i++)
      (res.operator[](i) -= Q[i]) %= mod,
          (res.operator[](i) += mod) %= mod;
    res.del_zero();
    return res;
  }
  poly& operator-=(const this_type& Q)
  {
    poly_base.resize(std::max(this->size(), Q.size()));
    for (std::size_t i = 0; i != size(); i++)
      (this->operator[](i) += mod - Q[i]) %= mod;
    del_zero();
    return *this;
  }

  struct DFT_BASE
  {
    void operator()(const std::size_t _len,
        std::vector<long long>& _con) const
    {
      if (_len == 1)
        return;
      const std::size_t _half = _len >> 1;
      std::vector<long long> _con1(_half), _con2(_half);
      for (std::size_t i = 0; i != _half; i++)
      {
        _con1[i] = _con[i << 1];
        _con2[i] = _con[i << 1 | 1];
      }
      this->operator()(_half, _con1);
      this->operator()(_half, _con2);
      long long w = 1ll;
      const long long w0
          = qp[__builtin_ctz((mod - 1) / _len / ebase)];
      for (std::size_t i = 0; i != _half;
           i++, (w *= w0) %= mod)
      {
        _con[i] = (_con1[i] + w * _con2[i] % mod) % mod;
        _con[i + _half]
            = (_con1[i] - w * _con2[i] % mod + mod) % mod;
      }
      return;
    }
  };
  struct IDFT_BASE
  {
    void operator()(const std::size_t _len,
        std::vector<long long>& _con) const
    {
      if (_len == 1)
        return;
      const std::size_t _half = _len >> 1;
      std::vector<long long> _con1(_half), _con2(_half);
      for (std::size_t i = 0; i != _half; i++)
      {
        _con1[i] = _con[i << 1];
        _con2[i] = _con[i << 1 | 1];
      }
      this->operator()(_half, _con1);
      this->operator()(_half, _con2);
      long long w = 1ll;
      const long long w0
          = qpinv[__builtin_ctz((mod - 1) / _len / ebase)];
      for (std::size_t i = 0; i != _half;
           i++, w = w * w0 % mod)
      {
        _con[i] = (_con1[i] + w * _con2[i] % mod) % mod;
        _con[i + _half]
            = (_con1[i] - w * _con2[i] % mod + mod) % mod;
      }
      return;
    }
  };

  inline int get_len(int limit) const
  {
    int len;
    for (len = 1; len < limit; len <<= 1)
      ;
    return len;
  }
  void DFT(int limit)
  {

    if (limit != (int)poly_base.size())
      poly_base.resize(limit);
    DFT_BASE()(limit, poly_base);
    return;
  }
  void IDFT(int limit)
  { // suppose that the len = 2^k
    IDFT_BASE()(limit, poly_base);
    const LL inv = builtin_quick_pow(limit, mod - 2);
    for (auto& val : poly_base)
      val = val * inv % mod;
  }

  poly operator*(const this_type& Q) const
  {
    if (this->empty() && Q.empty())
      return poly();
    int tar = size() + Q.size() - 1u;
    int len;
    for (len = 1; len < tar; len <<= 1)
      ;
    std::vector<long long> res(len), lft(len), rht(len);
    copy(poly_base.begin(), poly_base.end(), lft.begin());
    copy(Q.poly_base.begin(), Q.poly_base.end(),
        rht.begin());
    DFT_BASE()(len, lft);
    DFT_BASE()(len, rht);
    for (int i = 0; i != len; i++)
      res[i] = lft[i] * rht[i] % mod;
    IDFT_BASE()(len, res);
    // while (res.back() == 0) res.pop_back();
    const long long leninv
        = builtin_quick_pow(len, mod - 2);
    for (long long& val : res)
      val = val * leninv % mod;
    res.resize(tar);
    return poly(res);
  }

  poly& operator*=(const this_type& Q)
  {
    auto res = *this * Q;
    this->resize(res.size());
    for (int i = 0; i != (int)size(); i++)
      this->operator[](i) = res[i];
    return *this;
  }

  inline poly& operator=(
      const std::initializer_list<long long> _list)
  {
    poly_base = _list;
    reverse(poly_base.begin(), poly_base.end());
    del_zero();
    return *this;
  }
  inline poly& operator=(const std::vector<long long> _vec)
  {
    poly_base = std::move(_vec);
    return *this;
  }

  poly deri() const
  {
    if (size() <= 1u)
      return poly();
    std::vector<long long> res(size() - 1u);
    const int siz = static_cast<int>(size());
    for (int i = 0; i != siz - 1; i++)
      res[i] = get(i + 1) * (i + 1) % mod;
    return res;
  }
  poly& to_deri()
  {
    if (empty())
      return *this;
    const int siz = static_cast<int>(size());
    for (int i = 0; i != siz - 1; i++)
      this->operator[](i) = get(i) * (i + 1) % mod;
    poly_base.pop_back();
    return *this;
  }
  poly inte() const
  {
    if (empty())
      return poly();
    std::vector<long long> res(size() + 1u);
    const int siz = static_cast<int>(size());
    std::vector<long long> numinv(siz + 1);
    numinv[1] = 1;
    for (int i = 2; i <= siz; i++)
      numinv[i] = (long long)(mod - mod / i)
          * numinv[mod % i] % mod;
    for (int i = 1; i <= siz; i++)
    {
      res[i] = get(i - 1) * numinv[i] % mod;
    }
    return poly(res);
  }
  poly& to_inte()
  {
    if (empty())
      return *this;
    const int siz = static_cast<int>(size());
    std::vector<long long> numinv(siz + 1);
    numinv[1] = 1;
    for (int i = 2; i <= siz; i++)
      numinv[i] = (long long)(mod - mod / i)
          * numinv[mod % i] % mod;
    this->poly_base.emplace_back(0);
    for (int i = siz; i >= 1; i--)
    {
      this->operator[](i) = get(i - 1) * numinv[i] % mod;
    }
    this->operator[](0) = 0;
    return *this;
  }

  poly inv() const
  {
    return inv((int)size());
  }
  poly inv(int len) const
  {
    if (len == 1)
    {
      return poly(vector<long long> { builtin_quick_pow(
          this->operator[](0), mod - 2) });
    }

    poly lft = vector<long long>(
        poly_base.begin(), poly_base.begin() + len);
    poly rht = inv((len + 1) >> 1);

    int glen = get_len(len << 1);

    lft.DFT(glen);
    rht.DFT(glen);

    for (int i = 0; i != glen; i++)
      lft[i] = rht[i] * (2ll - lft[i] * rht[i] % mod + mod)
          % mod;

    lft.IDFT(glen);
    lft.resize(len);

    return lft;
  }
  poly ln() const
  {
    auto res = inv() * deri();
    res.resize(size());
    res.to_inte();
    res.resize(size());
    return res;
  }
  poly exp() const { return exp((int)size()); }
  poly exp(int len) const
  {
    if (len == 1)
    {
      return vector<long long> { 1 };
    }

    poly tmp = exp((len + 1) >> 1);
    tmp.resize(len);
    poly lntmp = tmp.ln();
    lntmp.resize(len);

    for (int i = 0; i != len; i++)
      lntmp[i]
          = (this->operator[](i) - lntmp[i] + mod) % mod;

    int glen = get_len(len << 1);

    tmp.DFT(glen);
    lntmp.DFT(glen);

    for (int i = 0; i != glen; i++)
      tmp[i] = tmp[i] * (lntmp[i] + 1) % mod;

    tmp.IDFT(glen);
    tmp.resize(len);

    return tmp;
  }

  poly pow(int k) const
  {
    poly tmp = ln();
    for (auto& val : tmp.poly_base)
      val = val * k % mod;
    return tmp.exp();
  }
  poly operator/(const poly &other) const 
  {
    poly lft = *this, rht = other;
    reverse(lft.poly_base.begin(), lft.poly_base.end());
    reverse(rht.poly_base.begin(), rht.poly_base.end());
    const int tar = lft.size() - rht.size() + 1;
    rht.resize(tar);
    poly res = lft * rht.inv();
    res.resize(tar);
    reverse(res.poly_base.begin(), res.poly_base.end());
    return res;
  }
  pair<poly, poly> div_mod(const poly &other) const 
  {
    poly lft = *this, rht = other;
    reverse(lft.poly_base.begin(), lft.poly_base.end());
    reverse(rht.poly_base.begin(), rht.poly_base.end());
    const int tar = lft.size() - rht.size() + 1;
    rht.resize(tar);
    poly res1 = lft * rht.inv();
    res1.resize(tar);
    reverse(res1.poly_base.begin(), res1.poly_base.end());
    poly res2 = *this - res1 * other;
    res2.resize(other.size() - 1);
    return make_pair(std::move(res1), std::move(res2));
  }

  inline friend std::istream& operator>>(
      std::istream& is, poly& val)
  {
    for (long long& _val : val.poly_base)
      is >> _val;
    return is;
  }
  inline friend std::ostream& operator<<(
      std::ostream& os, const poly& val)
  {
    for (const long long _val : val.poly_base)
      os << _val << ' ';
    return os;
  }
} X[N], Y[N];
int xx[N], yy[N];


int main()
{
  ios::sync_with_stdio(false);
  cin.tie(nullptr); cout.tie(nullptr);
  
  cin >> n >> m;

  for (int i = 1; i <= n; i++) cin >> lx[i].x >> lx[i].y;
  for (int i = 1; i <= m; i++) cin >> ly[i].x >> ly[i].y;

  for (int i = 1; i <= n; i++)
  {
    xx[i] = lx[i].x;
    X[i].resize(lx[i].y - lx[i].x + 1, 1);
  }
  for (int i = 1; i <= m; i++)
  {
    yy[i] = ly[i].x;
    Y[i].resize(ly[i].y - ly[i].x + 1, 1);    
  }

  for (int i = 2; i <= n; i++)
    X[i] = X[i] * X[i - 1], xx[i] += xx[i - 1];
  for (int i = 2; i <= m; i++)
    Y[i] = Y[i] * Y[i - 1], yy[i] += yy[i - 1];

  for (int i = 1; i <= n; i++, cout << '\n')
    for (int j = 1; j <= m; j++)
    {
      LL ans = 0;
      const auto siz = min(X[i].size(), Y[j].size());
      if (X[i].size() <= Y[j].size())
      {
        for (std::size_t p = 0u; p != siz; p++)
          ad(ans, X[i].get(p) * Y[j].get(p + xx[i] - yy[j]));
      } 
      else 
      {
        for (std::size_t p = 0u; p != siz; p++)
          ad(ans, Y[j].get(p) * X[i].get(p + yy[j] - xx[i]));
      }
      cout << ans << ' ';
    }

  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

2 3
1 2
2 3
1 4
2 2
1 3

output:

2 0 0 
3 4 4 

result:

ok 6 numbers

Test #2:

score: -100
Time Limit Exceeded

input:

500 500
19 458
1 480
7 485
50 461
12 476
15 461
48 466
40 453
46 467
9 458
27 478
26 472
46 459
29 490
6 500
17 487
48 484
28 472
28 459
25 480
4 491
29 481
36 460
2 491
44 499
22 473
20 458
4 483
27 471
2 496
11 461
43 450
2 478
37 466
15 459
42 482
7 451
19 455
2 453
47 475
48 450
1 474
46 471
9 4...

output:


result: