結果
問題 | No.1347 HS Railway |
ユーザー |
![]() |
提出日時 | 2021-01-15 18:57:39 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 5,398 bytes |
コンパイル時間 | 3,010 ms |
コンパイル使用メモリ | 215,656 KB |
最終ジャッジ日時 | 2025-01-17 18:21:32 |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | WA * 1 RE * 1 |
other | RE * 50 |
ソースコード
#include <bits/stdc++.h>template <class T>using Vec = std::vector<T>;constexpr unsigned MOD = 998244353;struct Fp {unsigned val;explicit Fp(const unsigned val = 0): val(val) { }void operator += (const Fp other) {val += other.val;if (val >= MOD) {val -= MOD;}}void operator -= (const Fp other) {val += MOD - other.val;if (val >= MOD) {val -= MOD;}}void operator *= (const Fp other) {val = (unsigned long long) val * other.val % MOD;}Fp operator + (const Fp other) const {Fp ret(*this);ret += other;return ret;}Fp operator - (const Fp other) const {Fp ret(*this);ret -= other;return ret;}Fp operator * (const Fp other) const {Fp ret(*this);ret *= other;return ret;}Fp inv() const {Fp ret(1), mult(*this);unsigned exp = MOD - 2;while (exp > 0) {if (exp & 1) {ret *= mult;}exp >>= 1;mult *= mult;}return ret;}};struct FpUtil {Vec<Fp> fact;Vec<Fp> inv_fact;explicit FpUtil(const unsigned size): fact(size + 1), inv_fact(size + 1) {fact[0] = Fp(1);for (int i = 1; i <= (int) size; ++i) {fact[i] = fact[i - 1] * Fp(i);}inv_fact[size] = fact[size].inv();for (int i = (int) size; i >= 1; --i) {inv_fact[i - 1] = inv_fact[i] * Fp(i);}}Fp binom(const unsigned a, const unsigned b) const {return fact[a + b] * inv_fact[a] * inv_fact[b];}};int main() {int N, M, L, K;std::cin >> N >> M >> L >> K;assert(1 <= N && N <= 200000);assert(0 <= M && M <= std::min(N - 1, 100000));assert(0 <= L && L <= std::min((long long) (N + 1) * (N + 1), (long long) 100));assert(0 <= K && K <= 100000);Vec<std::pair<int, int>> Pts;Pts.reserve(2 + M);Pts.emplace_back(0, 0);for (int i = 0; i < M; ++i) {int x, y;std::cin >> x >> y;Pts.emplace_back(x, y);}Pts.emplace_back(N, N);for (int i = 0; i + 1 < (int) Pts.size(); ++i) {assert(Pts[i].first < Pts[i + 1].first);assert(Pts[i].second < Pts[i + 1].second);}std::set<std::pair<int, int>> set;for (int i = 0; i < L; ++i) {int x, y;std::cin >> x >> y;assert(0 <= x && x <= N);assert(0 <= y && y <= N);set.emplace(x, y);}assert((int) set.size() == L);Vec<Vec<std::pair<int, int>>> Tig(Pts.size());for (int i = 0; i + 1 < (int) Pts.size(); ++i) {Tig[i + 1].push_back(Pts[i]);}Vec<bool> inevitable(Pts.size());for (const auto [x, y]: set) {bool inside = true;for (int i = 0; i < (int) Pts.size(); ++i) {if (x == Pts[i].first && y == Pts[i].second) {inevitable[i] = true;inside = false;break;}}if (!inside) {continue;}for (int i = 1; i < (int) Pts.size(); ++i) {if (Pts[i - 1].first <= x && x <= Pts[i].first && Pts[i - 1].second <= y && y <= Pts[i].second) {Tig[i].emplace_back(x, y);break;}}}for (int i = 1; i < (int) Pts.size(); ++i) {Tig[i].push_back(Pts[i]);}Vec<Fp> dp(L + 1);dp[inevitable[0]] = Fp(1);FpUtil util(2 * N);int max = 0;for (int i = 1; i < (int) Pts.size(); ++i) {const auto &vec = Tig[i];const int size = (int) vec.size();max = std::max(max, size);Vec<Vec<Fp>> path(size, Vec<Fp>(size));for (int j = 0; j < size; ++j) {for (int k = j + 1; k < size; ++k) {if (vec[k].second < vec[j].second) {continue;}path[j][k] = util.binom(vec[k].first - vec[j].first, vec[k].second - vec[j].second);for (int l = j + 1; l < k; ++l) {if (vec[l].second >= vec[j].second && vec[k].second >= vec[l].second) {path[j][k] -= path[j][l] * util.binom(vec[k].first - vec[l].first, vec[k].second - vec[l].second);}}}}Vec<Vec<Fp>> calc(size - 2, Vec<Fp>(L + 1));for (int j = 0; j < size - 2; ++j) {for (int k = 0; k < L; ++k) {calc[j][k + 1] += dp[k] * path[0][j + 1];}}for (int j = 0; j < size - 2; ++j) {for (int k = j + 1; k < size - 2; ++k) {for (int l = 0; l < L; ++l) {calc[k][l + 1] += calc[j][l] * path[j + 1][k + 1];}}}Vec<Fp> next(L + 1);for (int k = 0; k + inevitable[i] <= L; ++k) {next[k + inevitable[i]] += dp[k] * path[0][size - 1];for (int j = 0; j < size - 2; ++j) {next[k + inevitable[i]] += calc[j][k] * path[j + 1][size - 1];}}dp = std::move(next);}assert(max <= 100);std::cout << std::accumulate(dp.begin(), dp.begin() + std::min(L, K) + 1, Fp(0)).val << '\n';}