結果

問題 No.1347 HS Railway
ユーザー KoD
提出日時 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
権限があれば一括ダウンロードができます

ソースコード

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

#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';
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0