QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#564486 | #5145. Shortest Path | nhuang685 | WA | 39ms | 35996kb | C++23 | 10.1kb | 2024-09-15 06:57:36 | 2024-09-15 06:57:37 |
Judging History
answer
/**
* @author n685
* @brief
* @date 2024-09-14 17:58:33
*
*
*/
#include "bits/stdc++.h"
#ifdef LOCAL
#include "dd/debug.h"
#else
#define dbg(...) 42
#define dbg_proj(...) 420
#define dbg_rproj(...) 420420
void nline() {}
void bar() {}
void start_clock() {}
void end_clock() {}
#endif
namespace rs = std::ranges;
namespace rv = std::views;
template <class T> constexpr T INF = T{};
template <std::floating_point T>
constexpr T INF<T> = std::numeric_limits<T>::infinity();
template <> constexpr int INF<int> = 0x3f3f3f3f; // 1061109567
template <>
constexpr int64_t INF<int64_t> = 0x3f3f3f3f3f3f3f3f; // 4557430888798830399
template <class T> constexpr std::pair<T, T> ex_eucl(T a, T b) {
if (a < b) {
auto [x, y] = ex_eucl(b, a);
return {y, x};
}
if (b == 0) {
assert(a == 1);
return {1, 0};
}
auto [x, y] = ex_eucl(b, a % b);
return {y, x - (a / b) * y};
}
template <class Md, class V = int64_t>
requires std::signed_integral<std::decay_t<decltype(Md::value)>>
struct Mod {
using T = std::decay_t<decltype(Md::value)>;
T val = 0;
static constexpr T normalize(std::integral auto val) {
using U = decltype(Md::value + val);
U uval = static_cast<U>(val);
U umd = static_cast<U>(Md::value);
if (uval <= -umd || umd <= uval) {
uval %= umd;
}
if (val < 0) {
uval += umd;
}
return static_cast<T>(uval);
}
constexpr Mod() : val(0) {}
constexpr explicit Mod(std::integral auto _val) : val(normalize(_val)) {}
static inline const Mod ZERO = Mod(0);
static inline const Mod ONE = Mod(1);
static inline const Mod TWO = Mod(2);
// addition
constexpr Mod &operator+=(Mod b) {
val += b.val;
if (val >= Md::value) {
val -= Md::value;
}
return *this;
}
friend constexpr Mod operator+(Mod a, Mod b) { return a += b; }
constexpr Mod &operator++() { return *this += Mod(1); }
constexpr Mod operator++(int) {
Mod res = *this;
++(*this);
return res;
}
// subtraction
constexpr Mod &operator-=(Mod b) {
val -= b.val;
if (val < 0) {
val += Md::value;
}
return *this;
}
friend constexpr Mod operator-(Mod a, Mod b) { return a -= b; }
constexpr Mod &operator--() { return *this -= Mod(1); }
constexpr Mod operator--(int) {
Mod res = *this;
--(*this);
return res;
}
// negation
constexpr Mod operator-() const { return Mod(-val); }
// multiplication
constexpr Mod &operator*=(Mod b) {
val = static_cast<T>(static_cast<V>(val) * b.val % Md::value);
return *this;
}
friend constexpr Mod operator*(Mod a, Mod b) { return a *= b; }
constexpr Mod binpow(std::integral auto b) const {
Mod res = Mod(1), a = *this;
while (b > 0) {
if (b % 2 == 1) {
res *= a;
}
a *= a;
b /= 2;
}
return res;
}
// factorial
// align with fft, if code fails to compile make this smaller (if using array)
static constexpr int MXINV = 1 << 22;
static inline bool init = false;
static inline std::vector<Mod> ff, iff;
static void reset_fac() { init = false; }
static void init_fac() {
if (init) {
return;
}
ff.resize(MXINV + 1);
ff[0] = Mod(1);
for (int i = 1; i <= MXINV; ++i) {
ff[i] = ff[i - 1] * Mod(i);
}
iff.resize(MXINV + 1);
iff[MXINV] = ff[MXINV].large_inv();
for (int i = MXINV - 1; i >= 0; --i) {
iff[i] = iff[i + 1] * Mod(i + 1);
}
init = true;
}
static Mod fac(int v) {
if (!init) {
init_fac();
}
return ff[v];
}
static Mod ifac(int v) {
if (!init) {
init_fac();
}
return iff[v];
}
static Mod comb(int n, int k) {
if (n < 0 || k < 0 || n < k) {
return Mod(0);
}
return fac(n) * ifac(n - k) * ifac(k);
}
static Mod perm(int n, int k) {
if (n < 0 || k < 0 || n < k) {
return Mod(0);
}
return fac(n) * ifac(n - k);
}
// inverse
Mod small_inv() const {
return ifac(static_cast<int>(val)) * fac(static_cast<int>(val) - 1);
}
constexpr Mod large_inv() const {
return Mod(ex_eucl(static_cast<V>(val), static_cast<V>(Md::value)).first);
// return binpow(Md::value - 2);
}
Mod inv() const {
if (val <= MXINV) {
return small_inv();
}
return large_inv();
}
// sqrt
std::optional<Mod> sqrt() {
static std::mt19937 rng(
std::chrono::steady_clock::now().time_since_epoch().count()
);
Mod c = Mod::ZERO;
while ((c * c - *this).binpow((Md::value - 1) / 2) == Mod::ONE) {
c = Mod(rng());
}
if (c == Mod::ZERO) {
return std::nullopt;
}
std::pair<Mod, Mod> res(Mod::ONE, Mod::ZERO), a(c, Mod::ONE);
T b = (Md::value + 1) / 2;
auto mul = [&c, this](
const std::pair<Mod, Mod> &u,
const std::pair<Mod, Mod> &v
) -> std::pair<Mod, Mod> {
return {
u.first * v.first + u.second * v.second * (c * c - *this),
u.second * v.first + u.first * v.second
};
};
while (b > 0) {
if (b % 2 == 1) {
res = mul(res, a);
}
a = mul(a, a);
b /= 2;
}
return res.first;
// return std::min(res.first, -res.first);
}
// comparison
constexpr bool operator==(const Mod &b) const = default;
constexpr std::strong_ordering operator<=>(const Mod &b) const = default;
// io
friend std::istream &operator>>(std::istream &in, Mod &a) {
int64_t v;
in >> v;
a = Mod(v);
return in;
}
friend std::ostream &operator<<(std::ostream &out, const Mod &a) {
out << a.val;
return out;
}
// conversion
constexpr T value() const { return val; }
};
#if defined(LOCAL) && __cplusplus >= 202302L
template <class Md, class V>
requires std::formattable<typename Mod<Md, V>::T, char>
struct std::formatter<Mod<Md, V>, char> {
using T = typename Mod<Md, V>::T;
std::formatter<T, char> underlying;
constexpr formatter() {
if constexpr (requires { underlying.set_debug_format(); }) {
underlying.set_debug_format();
}
}
template <class ParseContext> constexpr auto parse(ParseContext &ctx) {
return underlying.parse(ctx);
}
template <class FormatContext>
auto format(const Mod<Md, V> &val, FormatContext &ctx) const {
return underlying.format(val.value(), ctx);
}
};
#endif
constexpr int MOD = 998'244'353;
using Mint = Mod<std::integral_constant<std::decay_t<decltype(MOD)>, MOD>>;
struct Node {
int64_t dist;
int node, level;
auto operator<=>(const Node &b) const = default;
};
struct Frac {
int64_t a, b; // a / b
auto operator<=>(const Frac &f) const { return a * f.b <=> b * f.a; }
int64_t trunc() const { return a / b; }
};
struct Line {
int64_t a, b;
auto operator<=>(const Line &b) const = default;
int64_t operator()(int64_t x) const { return a * x + b; }
Frac inter(const Line &rhs) const {
assert(a != rhs.a);
return Frac{rhs.b - b, a - rhs.a};
}
};
void solve() {
int n, m;
int64_t x;
std::cin >> n >> m >> x;
std::vector<std::vector<std::pair<int64_t, int>>> adj(n);
for (int i = 0; i < m; ++i) {
int a, b;
int64_t w;
std::cin >> a >> b >> w;
--a;
--b;
adj[a].emplace_back(w, b);
adj[b].emplace_back(w, a);
}
const int mx = 4 * n;
std::vector d0(n, std::vector(mx + 2, INF<int64_t>));
std::vector dn = d0;
auto dij = [&](int rt, std::vector<std::vector<int64_t>> &dist) {
std::priority_queue<Node, std::vector<Node>, std::greater<>> pq;
dist[rt][0] = 0;
pq.emplace(0, rt, 0);
while (!pq.empty()) {
auto [d, node, level] = pq.top();
pq.pop();
if (d > dist[node][level] || level == mx + 1) {
continue;
}
for (auto [w, i] : adj[node]) {
if (dist[i][level + 1] > dist[node][level] + w) {
dist[i][level + 1] = dist[node][level] + w;
pq.emplace(dist[i][level + 1], i, level + 1);
}
}
}
};
dij(0, d0);
Mint ans{0};
for (int i = 1; i <= std::min<int64_t>(x, mx - 1); ++i) {
ans += d0[n - 1][i] == INF<int64_t> ? Mint::ZERO : Mint{d0[n - 1][i]};
}
if (x <= mx - 1) {
std::cout << ans << '\n';
return;
}
dij(n - 1, dn);
std::vector dv(n, std::array<int64_t, 2>{INF<int64_t>, INF<int64_t>});
std::vector mi(n, INF<int64_t>);
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= mx; ++j) {
dv[i][0] = std::min(dv[i][0], d0[i][j] + dn[i][mx - j]);
}
for (int j = 0; j <= mx + 1; ++j) {
dv[i][1] = std::min(dv[i][1], d0[i][j] + dn[i][(mx + 1) - j]);
}
for (auto [w, j] : adj[i]) {
mi[i] = std::min(mi[i], w);
}
}
std::vector<int> ind(n);
std::iota(ind.begin(), ind.end(), 0);
rs::sort(ind, {}, [&](int v) { return mi[v]; });
std::array<std::deque<Line>, 2> dq;
dq.fill({Line{0, INF<int64_t>}});
for (int i : ind) {
if (mi[i] == INF<int64_t>) {
continue;
}
for (int t : {0, 1}) {
Line l{2 * mi[i], dv[i][t]};
if (!dq[t].empty() && l.b >= dq[t][0].b) {
continue;
}
while (!dq[t].empty() && l.a == dq[t][0].a) {
dq[t].pop_front();
}
while (std::ssize(dq[t]) > 1
&& l.inter(dq[t][0]) >= dq[t][0].inter(dq[t][1]))
{
dq[t].pop_front();
}
dq[t].push_front(l);
}
}
for (int t : {0, 1}) {
int64_t lst = (x - (mx + t)) / 2;
int64_t cl = 0;
for (int i = 0; i < std::ssize(dq[t]) - 1; ++i) {
int64_t cr = std::min(lst, dq[t][i].inter(dq[t][i + 1]).trunc());
ans += Mint{dq[t][i](cl) + dq[t][i](cr)} * Mint{cr - cl + 1}
* Mint::TWO.inv();
if (cr == lst) {
break;
}
cl = cr + 1;
}
}
std::cout << ans << '\n';
}
int main() {
#ifndef LOCAL
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#endif
int t;
std::cin >> t;
for (int i = 0; i < t; ++i) {
dbg(i + 1);
solve();
bar();
}
}
详细
Test #1:
score: 100
Accepted
time: 36ms
memory: 35996kb
input:
4 3 2 10 1 2 5 2 3 4 3 0 1000000000 3 3 100 1 2 3 1 3 4 2 3 5 4 6 1000000000 1 2 244 1 2 325 1 4 927 3 3 248 2 4 834 3 4 285
output:
125 0 15300 840659991
result:
ok 4 number(s): "125 0 15300 840659991"
Test #2:
score: -100
Wrong Answer
time: 39ms
memory: 35908kb
input:
400 4 7 850187899 1 2 83 1 2 24 3 1 23 2 3 80 3 3 65 1 2 55 2 4 31 4 7 297586795 3 4 54 1 1 66 2 2 75 1 3 68 1 4 27 1 4 29 2 3 96 5 7 217277444 3 3 9 3 4 36 2 2 77 5 5 38 3 3 6 1 2 18 1 2 23 5 6 379032278 5 5 96 4 3 92 3 2 49 4 3 44 1 4 19 1 1 18 5 6 534284598 5 1 59 1 2 2 3 3 55 2 2 24 5 4 34 2 4 7...
output:
191476186 406722183 0 0 58483482 115858544 177378789 656019644 858116309 0 38761681 633010531 0 696693112 919354187 122684249 865793975 91541737 248634956 0 374201737 455984810 284991806 322357914 0 514668426 407812429 555256220 0 419773408 989291360 743372489 0 716008724 0 189418326 244106015 41273...
result:
wrong answer 252nd numbers differ - expected: '590217722', found: '993655287'