結果

問題 No.1474 かさまJ
ユーザー btk
提出日時 2021-04-09 22:44:54
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 218 ms / 2,500 ms
コード長 38,331 bytes
コンパイル時間 2,333 ms
コンパイル使用メモリ 205,392 KB
最終ジャッジ日時 2025-01-20 14:58:49
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 17
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

// https://yukicoder.me/problems/no/1474
#define STATIC_MOD 1e9 + 7
#ifdef BTK
/*<head>*/
# include "Template.hpp"
# include "num/ModInt.hpp"
/*</head>*/
#else
/*<body>*/
/* #region auto includes */
/* #region stl */
/*<stl>*/
# include <bits/stdc++.h>
# include <sys/types.h>
# include <unistd.h>
using namespace std;
/*</stl>*/
/* #endregion */
/* #region template/Grid.hpp*/
/**
* @brief
* @tparam T std::string std;:vector
* @tparam U
* @param grid R > 0
* @param material
* @return std::vector<T> material grid
*/
template <typename T, typename U>
inline std::vector<T> wrapGrid(std::vector<T> grid, U material) {
std::vector<T> wrappedGrid(grid.size() + 2,
T(grid[0].size() + 2, material));
for (std::size_t i = 0; i < grid.size(); i++) {
for (std::size_t j = 0; j < grid[i].size(); j++) {
wrappedGrid[i + 1][j + 1] = grid[i][j];
}
}
return wrappedGrid;
}
/**
* @brief
*
*/
constexpr int dr4[] = {0, 1, 0, -1};
constexpr int dc4[] = {-1, 0, 1, 0};
/* #endregion */
/* #region template/IO.hpp*/
/**
* @file IO.hpp
* @author btk
* @brief cin
* @version 0.2
* @date 2021-03-01
*
* @copyright Copyright (c) 2021
*/
/**
* @brief
*/
namespace io {
inline void enableFastIO() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
}
inline void setDigits(int digits) {
std::cout << std::fixed;
std::cout << std::setprecision(digits);
}
} // namespace io
/**
* @brief
* vectorcin
* @tparam T
* @param is
* @param v
* @return istream&
*/
template <typename T>
std::istream& operator>>(std::istream& is, std::vector<T>& v) {
for (auto& it : v) is >> it;
return is;
}
/* #endregion */
/* #region template/IncludeSTL.hpp*/
/**
* @file IncludeSTL.hpp
* @author btk
* @brief include
* @version 0.1
* @date 2019-07-21
* @todo 2includescript
* @copyright Copyright (c) 2019
*
*/
/* #endregion */
/* #region template/Loop.hpp*/
/**
* @file Loop.hpp
* @author btk
* @brief range
* @version 0.1
* @date 2019-07-13
*
* @copyright Copyright (c) 2019
*
*/
/**
* @brief
* range
* @details
* [bg,ed)
* @see range
*/
class reverse_range {
private:
struct I {
int x;
int operator*() { return x - 1; }
bool operator!=(I& lhs) { return x > lhs.x; }
void operator++() { --x; }
};
I i, n;
public:
/**
* @brief Construct a new reverse range object
*
* @param n
*/
reverse_range(int n) : i({0}), n({n}) {}
/**
* @brief Construct a new reverse range object
*
* @param i
* @param n
*/
reverse_range(int i, int n) : i({i}), n({n}) {}
/**
* @brief
* begin iterator
* @return I&
*/
I& begin() { return n; }
/**
* @brief
* end iterator
* @return I&
*/
I& end() { return i; }
};
/**
* @brief
* python range-based for
* @details
* [bg,ed)
* ! (reverse_range)
* O(1)
* 使unused_var使
*/
class range {
private:
struct I {
int x;
int operator*() { return x; }
bool operator!=(I& lhs) { return x < lhs.x; }
void operator++() { ++x; }
};
I i, n;
public:
/**
* @brief Construct a new range object
*
* @param n
*/
range(int n) : i({0}), n({n}) {}
/**
* @brief Construct a new range object
*
* @param i
* @param n
*/
range(int i, int n) : i({i}), n({n}) {}
/**
* @brief
* begin iterator
* @return I&
*/
I& begin() { return i; }
/**
* @brief
* end iterator
* @return I&
*/
I& end() { return n; }
/**
* @brief
* range(reverse_ranges)
* @return reverse_range
*/
reverse_range operator!() { return reverse_range(*i, *n); }
};
/* #endregion */
/* #region template/Macro.hpp*/
/**
* @file Macro.hpp
* @author btk
* @brief LL
* @version 0.1
* @date 2019-07-13
*
* @copyright Copyright (c) 2019
*
*/
/**
* @def DEBUG
* @brief if if(0)
*/
/*</head>*/
# ifdef BTK
# define DEBUG if (1)
# else
# define DEBUG if (0)
# endif
/**
* @def ALL(v)
* @brief
* ALL
*/
# define ALL(v) (v).begin(), (v).end()
/**
* @def REC(ret, ...)
* @brief
*
*/
# define REC(ret, ...) std::function<ret(__VA_ARGS__)>
/**
* @def VAR_NAME(var)
* @brief
*/
# define VAR_NAME(var) # var
/**
* @brief
* range使
*/
template <typename T>
inline T& unused_var(T& v) {
return v;
}
template <typename T>
std::vector<T> nestingVector(std::size_t size) {
return std::vector<T>(size);
}
template <typename T, typename... Ts>
inline auto nestingVector(std::size_t size, Ts... ts) {
return std::vector<decltype(nestingVector<T>(ts...))>(
size, nestingVector<T>(ts...));
}
/* #endregion */
/* #region template/ChainOperation.hpp*/
/**
* @file ChainOperation.hpp
* @author btk
* @brief
*/
/**
* @brief
* @tparam F
* @tparam T
* @param v
* @return T
*/
template <typename F, typename T>
inline T chain(T&& v) {
return v;
}
/**
* @brief
* @tparam F
* @tparam T
* @tparam Ts
* @param head
* @param tail
* @return T
*/
template <typename F, typename T, typename... Ts>
inline auto chain(const T head, Ts&&... tail) {
return F::exec(head, chain<F>(tail...));
}
/**
* @brief
* ·F
* @tparam F
* @tparam T
* @tparam Ts
* @param target
* @param candidates
* @return true
* @return false
*/
template <typename F, typename T, typename... Ts>
inline bool changeTarget(T& target, Ts&&... candidates) {
const T old = target;
target = chain<F>(target, candidates...);
return old != target;
}
/* #endregion */
/* #region template/Math.hpp*/
/**
* @file Math.hpp
* @author btk
* @brief
*/
/**
* @brief gcd, ceilstd
*/
namespace math {
/**
* @brief
* @details ax + by = gx,y
* @param a
* @param b
* @param x
* @param y
* @return int64_t g:ab
*/
int64_t extgcd(int64_t a, int64_t b, int64_t& x, int64_t& y) {
int64_t g = a;
x = 1;
y = 0;
if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x;
return g;
}
/**
* @brief
* @details betouzEquation
*/
struct BetouzSolution {
int64_t x, y, dx, dy;
};
/**
* @brief
* @details a(x + k*dx) + b(y -k*dy) = c x, y, dx, dy
* @param a
* @param b
* @param c
* @return int64_t nullopt
*/
std::optional<BetouzSolution> betouzEquation(int64_t a, int64_t b,
int64_t c) {
BetouzSolution sol;
const int64_t g = extgcd(a, b, sol.x, sol.y);
if (c % g == 0) {
return std::nullopt;
}
sol.dx = b / g;
sol.dy = a / g;
sol.x *= c / g;
sol.y *= c / g;
return sol;
}
namespace inner {
/**
* @brief 2gcd
* @tparam T
*/
template <typename T>
struct GCDFunc {
/**
* @brief
* @param l
* @param r
* @return T
*/
static inline T exec(T l, T r) {
while (r != 0) {
T u = l % r;
l = r;
r = u;
}
return l;
}
};
/**
* @brief 2gcd
* @tparam T
*/
template <typename T>
struct LCMFunc {
/**
* @brief
* @param l
* @param r
* @return T
*/
static inline T exec(T l, T r) {
return (l / GCDFunc<T>::exec(l, r)) * r;
}
};
} // namespace inner
/**
* @brief values
* @tparam Ts
* @param values gcd2
* @return int64
*/
template <typename... Ts>
inline int64_t gcd(Ts&&... values) {
return chain<inner::GCDFunc<int64_t>>(values...);
}
/**
* @brief values
* @tparam Ts
* @param values lcm2
* @return int64
*/
template <typename... Ts>
inline int64_t lcm(Ts&&... values) {
return chain<inner::LCMFunc<int64_t>>(values...);
}
/**
* @brief iterator lcm
* @tparam ITR iterator
* @param l
* @param r
* @return int64_t lcm
*/
template <typename ITR>
inline int64_t lcmAll(ITR l, ITR r) {
int64_t ret = 1;
for (auto it = l; it != r; ++it) {
ret = lcm(ret, *it);
}
return ret;
}
/**
* @brief container () lcm
* @tparam Container vectorlist
* @param container
* @return int64_t lcm
*/
template <typename Container>
inline int64_t lcmAll(Container container) {
int64_t ret = 1;
for (auto e : container) {
ret = lcm(ret, e);
}
return ret;
}
/**
* @brief iterator gcd
* @tparam ITR iterator
* @param l
* @param r
* @return int64_t lcm
*/
template <typename ITR>
inline int64_t gcdAll(ITR l, ITR r) {
int64_t ret = 0;
for (auto it = l; it != r; ++it) {
ret = gcd(ret, *it);
}
return ret;
}
/**
* @brief container () gcd
* @tparam Container vectorlist
* @param container
* @return int64_t gcd
*/
template <typename Container>
inline int64_t gcdAll(Container container) {
int64_t ret = 0;
for (auto e : container) {
ret = gcd(ret, e);
}
return ret;
}
/**
* @brief u/d
* @todo
* @tparam T
* @param u
* @param d
* @return T
*/
template <typename T>
inline T ceil(T u, T d) {
return (u + d - (T)1) / d;
}
} // namespace math
/**
* @brief 2
* @tparam T
*/
template <typename T>
struct minFunc {
/**
* @brief
* @param l
* @param r
* @return T
*/
static T exec(const T l, const T r) { return l < r ? l : r; }
};
/**
* @brief 2
*
* @tparam T
*/
template <typename T>
struct maxFunc {
/**
* @brief
*
* @param l
* @param r
* @return T
*/
static T exec(const T l, const T r) { return l > r ? l : r; }
};
/**
* @brief
* @see chain
* @tparam T
* @tparam Ts
* @param head
* @param tail
* @return T
*/
template <typename T, typename... Ts>
inline T minOf(T head, Ts... tail) {
return chain<minFunc<T>>(head, tail...);
}
/**
* @brief
* @see chain
* @tparam T
* @tparam Ts
* @param head
* @param tail
* @return T
*/
template <typename T, typename... Ts>
inline T maxOf(T head, Ts... tail) {
return chain<maxFunc<T>>(head, tail...);
}
/**
* @brief change min
* @tparam T
* @param target
* @param candidates
* @return true
*/
template <typename T, typename... Ts>
inline bool chmin(T& target, Ts&&... candidates) {
return changeTarget<minFunc<T>>(target, candidates...);
}
/**
* @brief chminmax
* @see chmin
* @tparam T
* @param target
* @param candidates
* @return true
*/
template <typename T, typename... Ts>
inline bool chmax(T& target, Ts&&... candidates) {
return changeTarget<maxFunc<T>>(target, candidates...);
}
/* #endregion */
/* #region template/Random.hpp*/
/**
* @file Random.hpp
* @author btk
* @brief
* @version 0.1
* @date 2019-07-13
* @copyright Copyright (c) 2019
*/
//! ID
const pid_t pid = getpid();
/**
* @brief XorShift32
*/
class XorShift32 {
private:
//! XorShift
unsigned value;
/**
* @brief XorShift32 value
*/
inline void update() {
value = value ^ (value << 13);
value = value ^ (value >> 17);
value = value ^ (value << 5);
}
/**
* @brief
* @return unsigned value
*/
inline unsigned get() {
unsigned v = value;
update();
return v;
}
public:
/**
* @brief [0, 2^bit)
* @tparam 31
* @return int
*/
template <int bit = 31>
inline int next_int() {
return (int)(get() >> (32 - bit));
}
/**
* @brief [-2^bit,2^bit)
* @tparam 31
* @return int
*/
template <int bit = 31>
inline int next_signed() {
unsigned v = get();
return (int)((v >> (31 - bit)) - (1 << (bit)));
}
/**
* @brief next_int
* @tparam 31
* @return int
*/
template <int bit = 31>
inline int range_max() {
return (int)((1u << bit) - 1);
};
/**
* @brief Construct a new XorShift32 object
* @param seed
* @details valueXorShift32
*/
XorShift32(const unsigned seed) {
value = seed;
update();
}
/**
* @brief Construct a new XorShift 32 object
* @details IDXorShift32
*/
XorShift32() : XorShift32(pid) {}
};
/* #endregion */
/* #region template/STLExtension.hpp*/
/**
* @file STLExtension.hpp
* @brief STL
*/
namespace ext {
/**
* @brief std::sortWrapper
* @tparam Container std::vectorstd::list
* @param container
* @return Container&
* ==
*/
template <typename Container>
inline Container& sort(Container& container) {
sort(std::begin(container), std::end(container));
return container;
}
/**
* @brief std::sortWrapper
* @tparam Container std::vectorstd::list
* @tparam Comparator
* @param container
* @param comparator
* @return Container&
* ==
*/
template <typename Container, typename Comparator>
inline Container& sort(Container& container, Comparator comparator) {
sort(std::begin(container), std::end(container), comparator);
return container;
}
/**
* @brief std::reverseWrapper
* @tparam Container std::vectorstd::list
* @param container
* @return Container&
* ==
*/
template <typename Container>
inline Container& reverse(Container& container) {
reverse(std::begin(container), std::end(container));
return container;
}
/**
* @brief std::accumulatevectorWrapper
* @tparam T
* @tparam U
* @param container
* @param zero
* @return U
*/
template <typename T, typename U>
inline U accumulate(const std::vector<T>& container, U zero) {
return std::accumulate(std::begin(container), std::end(container),
zero);
}
/**
* @brief std::accumulatevectorWrapper
* @tparam T &&
* @param container
* @return T overflow
*/
template <typename T>
inline T accumulate(const std::vector<T>& container) {
return accumulate(container, T(0));
}
/**
* @brief std::countWrapper
* @tparam Container std::vectorstd::list
* @tparam T
* @param container
* @param value
* @return int
*/
template <typename Container, typename T>
inline int count(Container& container, T value) {
return std::count(std::begin(container), std::end(container), value);
}
/**
* @brief vector
* @param n
* @param startFrom
* @param step
* @return std::vector<int>
*/
inline std::vector<int> iota(int n, int startFrom = 0, int step = 1) {
std::vector<int> container(n);
int v = startFrom;
for (int i = 0; i < n; i++, v += step) {
container[i] = v;
}
return container;
}
/**
* @brief
* (*max_element) wrapper
* @tparam ITR iterator
* @param l iterator
* @param r iterator
* @param defaultValue
* @return auto
*/
template <typename ITR>
inline auto maxIn(ITR l, ITR r,
std::remove_reference_t<decltype(*l)> defaultValue = 0) {
if (r == l) {
return defaultValue;
}
return *std::max_element(l, r);
}
/**
* @brief maxIn vector
* @tparam T
* @param containter
* @param defaultValue
* @return T defaultValue
*/
template <typename T>
inline T maxIn(std::vector<T> container, T defaultValue = 0) {
return maxIn(container.begin(), container.end(), defaultValue);
}
/**
* @brief
* (*min_element) wrapper
* @tparam ITR iterator
* @param l iterator
* @param r iterator
* @param defaultValue
* @return auto
*/
template <typename ITR>
inline auto minIn(ITR l, ITR r,
std::remove_reference_t<decltype(*l)> defaultValue = 0) {
if (r == l) {
return defaultValue;
}
return *std::min_element(l, r);
}
/**
* @brief minIn vector
* @tparam T
* @param containter
* @param defaultValue
* @return T defaultValue
*/
template <typename T>
inline T minIn(std::vector<T> container, T defaultValue = 0) {
return minIn(container.begin(), container.end(), defaultValue);
}
} // namespace ext
/* #endregion */
/* #region template/Strings.hpp*/
/**
* @file Strings.hpp
* @author btk
* @brief
*/
/**
* @brief
* @tparam T range-based for
* @tparam DelimiterType
* @param v
* @param delimiter
* @return std::string delimiter
*/
template <typename T, typename DelimiterType>
std::string join(const T& v, const DelimiterType& delimiter) {
std::stringstream ss;
bool isFirst = true;
for (auto& it : v) {
if (!isFirst) {
ss << delimiter;
}
isFirst = false;
ss << it;
}
return ss.str();
}
/**
* @brief
* @tparam ITR
* @tparam DelimiterType
* @param bg
* @param ed
* @param delimiter
* @return std::string delimiter
*/
template <typename ITR, typename DelimiterType>
std::string join(const ITR bg, const ITR ed, const DelimiterType& delimiter) {
std::stringstream ss;
bool isFirst = true;
for (auto it = bg; it != ed; ++it) {
if (!isFirst) {
ss << delimiter;
}
isFirst = false;
ss << *it;
}
return ss.str();
}
/**
* @brief Strings.hpp
*/
namespace strings {
/**
* @brief std::size_tWrap
* @tparam i
*/
template <std::size_t i>
struct IndexWrapper {};
/**
* @brief tuplejoin使
* @tparam CurrentIndex index
* @tparam LastIndex index
* @tparam DelimiterType
* @tparam Ts tuple使
*/
template <typename CurrentIndex, typename LastIndex, typename DelimiterType,
typename... Ts>
struct JoinFunc;
/**
* @brief tuplejoin .join
* @tparam i id = tupleid
* @tparam DelimiterType
* @tparam Ts tuple使
*/
template <std::size_t i, typename DelimiterType, typename... Ts>
struct JoinFunc<IndexWrapper<i>, IndexWrapper<i>, DelimiterType, Ts...> {
/**
* @brief tuplejoin
* @param ss stringstream
* @param values tuple
* @param delimiter
* @return std::stringstream&
*/
static std::stringstream& join(std::stringstream& ss,
const std::tuple<Ts...>& values,
const DelimiterType& delimiter) {
unused_var(delimiter);
ss << std::get<i>(values);
return ss;
}
};
/**
* @brief tuplejoin
* @tparam i id
* @tparam j tupleid
* @tparam DelimiterType
* @tparam Ts
*/
template <std::size_t i, std::size_t j, typename DelimiterType,
typename... Ts>
struct JoinFunc<IndexWrapper<i>, IndexWrapper<j>, DelimiterType, Ts...> {
/**
* @brief tuplejoin
* @param ss stringstream
* @param values tuple
* @param delimiter
* @return std::stringstream&
*/
static std::stringstream& join(std::stringstream& ss,
const std::tuple<Ts...>& values,
const DelimiterType& delimiter) {
ss << std::get<i>(values);
ss << delimiter;
return JoinFunc<IndexWrapper<i + 1>, IndexWrapper<j>, DelimiterType,
Ts...>::join(ss, values, delimiter);
}
};
} // namespace strings
/**
* @brief join
* @tparam DelimiterType
* @tparam Ts
* @param values
* @param delimiter
* @return std::string
*/
template <typename DelimiterType, typename... Ts>
std::string join(const std::tuple<Ts...>& values,
const DelimiterType& delimiter) {
std::stringstream ss;
constexpr std::size_t lastIndex =
std::tuple_size<std::tuple<Ts...>>::value - 1u;
return strings::JoinFunc<strings::IndexWrapper<0>,
strings::IndexWrapper<lastIndex>, DelimiterType,
Ts...>::join(ss, values, delimiter)
.str();
}
/* #endregion */
/* #region Template.hpp*/
/**
* @file Template.hpp
* @brief
* @author btk15049
* @date 2019/05/02
*/
/* #endregion */
/* #region num/ModInt.hpp*/
# include <cstdint>
# include <utility>
/**
* @file ModInt.hpp
* @brief mod
* @author btk15049
* @date 2019/03/08
* @details
* \todo verify
* verify: CSA12ERUPC day3 F
*/
//! [WARNING!] mod constexpr
# ifdef STATIC_MOD
constexpr int mod = STATIC_MOD;
# else
int mod;
# endif
/**
* @brief mod
* @details
* mod
*/
class ModInt {
private:
//!
int x;
public:
/**
* @brief
* @details "cout << *ret << endl;"
*/
int64_t operator*() const { return x; }
/**
* @brief 0
*/
ModInt() { x = 0; }
/**
* @brief int
* @param[in] y
* @details
* modmod
*/
ModInt(const int y) { x = y; }
/**
* @brief int64_t
* @param[in] y
* @details mod
*/
ModInt(const int64_t y) { x = (int)((mod + y % mod) % mod); }
/**
* @brief ModInt
* @param[in] o
* @details
*/
ModInt(const ModInt& o) { this->x = *o; }
/**
* @brief ModInt使
* @param[in] x
* @details x[0,mod)
*/
static inline ModInt raw(const int64_t x) {
// assert(x<mod);
return ModInt((int)x);
}
/**
* @brief ModInt使
* @param[in] x
* @details mod2OK
*/
static inline ModInt get(const int64_t x) { return ModInt(x); }
/**
* @brief int
* @param[in] o
* @details
* modmod
*/
ModInt& operator=(const int o) {
this->x = o >= mod ? o - mod : o;
return *this;
}
/**
* @brief int64_t
* @param[in] o
* @details mod2OK
*/
ModInt& operator=(const int64_t o) {
this->x = (int)((mod + o % mod) % mod);
return *this;
}
/**
* @brief ModInt
* @param[in] o
* @details
*/
ModInt& operator=(const ModInt o) {
this->x = *o;
return *this;
}
};
/**
* @param[in] l ModInt
* @param[in] r ModInt
* @details if使
*/
inline ModInt add(const ModInt l, const ModInt r) {
const int64_t x = *l + *r;
return ModInt::raw(x >= mod ? x - mod : x);
}
/**
* @param[in] l ModInt
* @param[in] r ModInt
*/
inline ModInt mul(const ModInt l, const ModInt r) {
return ModInt::raw(*l * *r % mod);
}
/**
* @brief a^x %mod
* @param[in] a ModInt
* @param[in] x int64_t
*/
inline ModInt pow(ModInt a, int64_t x) {
ModInt ret = ModInt::raw(1);
while (x) {
if (x & 1) {
ret = mul(ret, a);
}
a = mul(a, a);
x >>= 1;
}
return ret;
}
/**
* @brief x^-1 %mod
* @param[in] x ModInt
* @details
* 使
* O(log(mod))
*/
inline ModInt inv(const ModInt x) {
int64_t a = *x, b = mod, u = 1, v = 0;
while (b) {
int64_t t = a / b;
std::swap(a -= t * b, b);
std::swap(u -= t * v, v);
}
return ModInt::get(u);
}
/**
* @brief
* @param[in] x ModInt
*/
inline ModInt operator-(const ModInt x) { return add(mod, -*x); }
/**
* @param[in] l ModInt
* @param[in] r ModInt
*/
inline ModInt operator+(const ModInt l, const ModInt r) { return add(l, r); }
/**
* @param[in] l ModInt
* @param[in] r ModInt
*/
inline ModInt operator*(const ModInt l, const ModInt r) { return mul(l, r); }
/**
* @param[in] l ModInt
* @param[in] r ModInt
*/
inline ModInt operator-(const ModInt l, const ModInt r) { return add(l, -r); }
/**
* @param[in] l ModInt
* @param[in] r int
* @details
* modraw使ModIntmod
*/
inline ModInt operator+(const ModInt l, const int r) {
return add(l, ModInt::raw(r));
}
/**
* @param[in] l ModInt
* @param[in] r int
*/
inline ModInt operator+(const ModInt l, const int64_t r) {
return add(l, ModInt::get(r));
}
/**
* @param[in] l ModInt
* @param[in] r int
* @details
* modraw使ModIntmod
*/
inline ModInt operator*(const ModInt l, const int r) {
return mul(l, ModInt::raw(r));
}
/**
* @param[in] l ModInt
* @param[in] r int
*/
inline ModInt operator*(const ModInt l, const int64_t r) {
return mul(l, ModInt::get(r));
}
/**
* @param[in] l ModInt
* @param[in] r int
* @details
* modraw使ModIntmod
*/
inline ModInt operator-(const ModInt l, const int r) {
return add(l, ModInt::raw(mod - r));
}
/**
* @param[in] l ModInt
* @param[in] r int
*/
inline ModInt operator-(const ModInt l, const int64_t r) {
return add(l, -ModInt::get(r));
}
/**
* @param[in] l ModInt
* @param[in] r int
* @details
* modraw使ModIntmod
*/
inline ModInt operator/(const ModInt l, const int r) {
return mul(l, inv(ModInt::raw(r)));
}
/**
* @param[in] l ModInt
* @param[in] r int
*/
inline ModInt operator/(const ModInt l, const int64_t r) {
return mul(l, inv(ModInt::get(r)));
}
/**
* @param[in] l ModInt
* @param[in] r int64_t
* @details
* pow(l,r)pow
O(log mod)
*/
inline ModInt operator^(const ModInt l, const int64_t r) { return pow(l, r); }
/**
* @brief
* +=operator+
* @tparam T
* @param l ModInt
* @param r
* @return ModInt&
*/
template <typename T>
ModInt& operator+=(ModInt& l, T r) {
l = l + r;
return l;
}
/**
* @brief
* -=operator-
* @tparam T
* @param l ModInt
* @param r
* @return ModInt&
*/
template <typename T>
ModInt& operator-=(ModInt& l, T r) {
l = l - r;
return l;
}
/**
* @brief
* *=operator*
* @tparam T
* @param l ModInt
* @param r
* @return ModInt&
*/
template <typename T>
ModInt& operator*=(ModInt& l, T r) {
l = l * r;
return l;
}
/**
* @namespace factorial
* @brief
* @details
* - combination
* - permutation
* - multiChoose
*/
namespace factorial {
//!
constexpr int size =
# ifdef FACTORIAL_SIZE
FACTORIAL_SIZE;
# else
3123456;
# endif
//!
bool is_build = false;
//!
ModInt factorial[size];
//! ()^-1
ModInt inverse_factorial[size];
/**
* @brief
* @details
* [0,size).
* O(size + log(mod))
*/
void build() {
is_build = true;
factorial[0] = 1;
for (int i = 1; i < size; i++) {
factorial[i] = factorial[i - 1] * i;
}
inverse_factorial[size - 1] = inv(factorial[size - 1]);
for (int i = size - 1; i >= 1; i--) {
inverse_factorial[i - 1] = inverse_factorial[i] * i;
}
}
/**
* @brief nPk
* @details
* O(1) is_build
*
*/
inline ModInt permutation(int n, int k) {
if (k < 0 || k > n) return ModInt::raw(0);
if (!is_build) build();
return factorial[n] * inverse_factorial[n - k];
}
/**
* @brief nCk
* @details
* O(1) is_build
*
*/
inline ModInt combination(int n, int k) {
if (k < 0 || k > n) return ModInt::raw(0);
if (!is_build) build();
return factorial[n] * inverse_factorial[k] * inverse_factorial[n - k];
}
/**
* @brief
* @param n (n-1)
* @param r
* @return ModInt nHr
*/
ModInt multiChoose(int n, int r) {
if (n == 0 && r == 0) return ModInt::raw(1);
return combination(n + r - 1, r);
}
/**
* @brief
* @details
* lim1,2,...,i
* O(min(n, r / lim))
* @param n
* @param r
* @param lim 1
* @return ModInt
*/
ModInt multiChoose(int n, int r, int lim) {
ModInt ret = 0;
for (int i = 0; i <= n; i++) {
if (i * (lim + 1) > r) break;
ret += ((i & 1) ? mod - 1 : 1) * combination(n, i)
* multiChoose(n, r - i * (lim + 1));
}
return ret;
}
} // namespace factorial
/* #endregion */
/* #endregion */
/*</body>*/
#endif
struct cww {
cww() {
io::enableFastIO();
io::setDigits(10);
}
} star;
int main() {
/* write here */
int N, p, q, L;
cin >> N >> p >> q >> L;
vector<int> S(N);
cin >> S;
using dpArray = vector<ModInt>;
vector<dpArray> dp(N + 1, dpArray(q + 1));
dp[0][0] = 1;
for (int i : range(N)) {
auto nx = dp;
for (int used : range(i + 1)) {
vector<ModInt> s(q + 2);
for (int j : range(q + 1)) {
s[j + 1] = s[j] + dp[used][j];
}
auto sum = [&](int l, int r) { return s[r] - s[l]; };
for (int j : range(1, q + 1)) {
nx[used + 1][j] += sum(max(0, j - S[i]), j);
}
}
swap(dp, nx);
}
ModInt ret = 0;
for (int used : range(N + 1)) {
for (int qq : range(q + 1)) {
const int pp = p - (L * used - qq);
if (pp < 0) continue;
if (*dp[used][qq] == 0) continue;
auto c = factorial::multiChoose(N, pp) * dp[used][qq];
ret += c;
}
}
cout << *ret << endl;
return 0;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0