結果
| 問題 |
No.1667 Forest
|
| コンテスト | |
| ユーザー |
KoD
|
| 提出日時 | 2021-09-03 22:06:52 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 86 ms / 3,000 ms |
| コード長 | 5,991 bytes |
| コンパイル時間 | 3,298 ms |
| コンパイル使用メモリ | 254,464 KB |
| 実行使用メモリ | 6,820 KB |
| 最終ジャッジ日時 | 2024-12-15 13:39:52 |
| 合計ジャッジ時間 | 4,624 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 15 |
ソースコード
#include <bits/stdc++.h>
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;
class rep {
struct Iter {
usize itr;
constexpr Iter(const usize pos) noexcept : itr(pos) {}
constexpr void operator++() noexcept { ++itr; }
constexpr bool operator!=(const Iter& other) const noexcept { return itr != other.itr; }
constexpr usize operator*() const noexcept { return itr; }
};
const Iter first, last;
public:
explicit constexpr rep(const usize first, const usize last) noexcept : first(first), last(std::max(first, last)) {}
constexpr Iter begin() const noexcept { return first; }
constexpr Iter end() const noexcept { return last; }
};
template <class T> constexpr T rem_euclid(T value, const T& mod) { return (value %= mod) >= 0 ? value : value + mod; }
template <class T> constexpr std::pair<T, T> inv_gcd(const T& a, const T& b) {
using U = std::make_signed_t<T>;
U t = rem_euclid(a, b);
if (t == 0) return {b, 0};
U s = b, m0 = 0, m1 = 1;
while (t != 0) {
const U u = s / t;
s -= t * u;
m0 -= m1 * u;
U tmp = s;
s = t;
t = tmp;
tmp = m0;
m0 = m1;
m1 = tmp;
}
if (m0 < 0) m0 += b / s;
return {(T)s, (T)m0};
}
template <class T> constexpr T mod_inv(const T& a, const T& mod) {
const auto [g, x] = inv_gcd(a, mod);
assert(g == 1);
return x;
}
template <usize ID> class DynamicModint {
using Mint = DynamicModint;
struct Barret {
u32 mod;
u64 near_inv;
explicit Barret(const u32 mod) noexcept : mod(mod), near_inv((u64)(-1) / mod + 1) {}
u32 product(const u32 a, const u32 b) const noexcept {
const u64 z = (u64)a * b;
const u64 x = ((u128)z * near_inv) >> 64;
const u32 v = z - x * mod;
return v < mod ? v : v + mod;
}
};
static inline auto bt = Barret(1);
u32 v;
public:
static u32 mod() noexcept { return bt.mod; }
static void set_mod(const u32 mod) noexcept {
assert((u32)1 <= mod and mod <= ((u32)1 << 31));
bt = Barret(mod);
}
template <class T, std::enable_if_t<std::is_signed_v<T> and std::is_integral_v<T>>* = nullptr>
static T normalize(const T x) noexcept {
return rem_euclid<std::common_type_t<T, i64>>(x, mod());
}
template <class T, std::enable_if_t<std::is_unsigned_v<T> and std::is_integral_v<T>>* = nullptr>
static T normalize(const T x) noexcept {
return x % mod();
}
DynamicModint() noexcept : v(0) {}
template <class T> DynamicModint(const T x) noexcept : v(normalize(x)) {}
template <class T> static Mint raw(const T x) noexcept {
Mint ret;
ret.v = x;
return ret;
}
u32 get() const noexcept { return v; }
Mint neg() const noexcept { return raw(v == 0 ? 0 : mod() - v); }
Mint inv() const noexcept { return raw(mod_inv(v, mod())); }
Mint pow(u64 exp) const noexcept {
Mint ret(1), mult(*this);
for (; exp > 0; exp >>= 1) {
if (exp & 1) ret *= mult;
mult *= mult;
}
return ret;
}
Mint operator-() const noexcept { return neg(); }
Mint operator~() const noexcept { return inv(); }
Mint operator+(const Mint& rhs) const noexcept { return Mint(*this) += rhs; }
Mint& operator+=(const Mint& rhs) noexcept {
if ((v += rhs.v) >= mod()) v -= mod();
return *this;
}
Mint operator-(const Mint& rhs) const noexcept { return Mint(*this) -= rhs; }
Mint& operator-=(const Mint& rhs) noexcept {
if (v < rhs.v) v += mod();
v -= rhs.v;
return *this;
}
Mint operator*(const Mint& rhs) const noexcept { return Mint(*this) *= rhs; }
Mint& operator*=(const Mint& rhs) noexcept {
v = bt.product(v, rhs.v);
return *this;
}
Mint operator/(const Mint& rhs) const noexcept { return Mint(*this) /= rhs; }
Mint& operator/=(const Mint& rhs) noexcept { return *this *= rhs.inv(); }
bool operator==(const Mint& rhs) const noexcept { return v == rhs.v; }
bool operator!=(const Mint& rhs) const noexcept { return v != rhs.v; }
friend std::ostream& operator<<(std::ostream& stream, const Mint& rhs) { return stream << rhs.v; }
};
using Modint = DynamicModint<__COUNTER__>;
template <class T> using Vec = std::vector<T>;
void main_() {
usize N;
u32 MOD;
std::cin >> N >> MOD;
Modint::set_mod(MOD);
Vec<Modint> fact, inv_fact;
fact.emplace_back(1);
inv_fact.emplace_back(1);
const auto get_fact = [&](const usize n) {
while (fact.size() <= n) {
fact.push_back(fact.back() * fact.size());
}
return fact[n];
};
const auto get_inv_fact = [&](const usize n) {
while (inv_fact.size() <= n) {
inv_fact.push_back(inv_fact.back() / inv_fact.size());
}
return inv_fact[n];
};
const auto binom = [&](const usize n, const usize r) {
return get_fact(n) * get_inv_fact(r) * get_inv_fact(n - r);
};
Vec<Modint> pre(N + 1);
pre[1] = 1;
for (const auto i : rep(2, N + 1)) {
pre[i] = Modint(i).pow(i - 2);
}
Vec<Vec<Modint>> dp(N + 1, Vec<Modint>(N));
dp[0][0] = 1;
for (const auto n : rep(0, N)) {
for (const auto e : rep(0, N)) {
if (dp[n][e].get() == 0) {
continue;
}
for (const auto k : rep(1, N - n + 1)) {
dp[n + k][e + k - 1] += dp[n][e] * binom(N - n - 1, k - 1) * pre[k];
}
}
}
for (const auto m : rep(0, N)) {
std::cout << dp[N][m] << '\n';
}
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
main_();
return 0;
}
KoD