ABC212E - Safety Journey

問題

https://atcoder.jp/contests/abc212/tasks/abc212_e

略説

dp[i][j] := i日目に都市jにいる場合の数

dp[i+1][j] = sum(dp[i]) - dp[i][k:=都市kと都市jは結ばれていない]

iについての各ループにおいて、kの総数は高々2M+Nとなる。

よって計算量は O(K(N+M)) となる。

ACコード
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
using namespace std;

template <unsigned int MOD>
struct Modint {
    unsigned int x;
    constexpr Modint(): x(0) {}
    template <typename T>
    constexpr Modint(T _x) noexcept : x((_x%=MOD)<0 ? _x+MOD : _x) {}
    constexpr Modint inv() const noexcept {
        long long a = x, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b;
            swap(a, b);
            u -= t * v;
            swap(u, v);
        }
        return Modint(u);
    }
    constexpr Modint operator+() const noexcept {return *this;}
    constexpr Modint operator-() const noexcept {return Modint()-*this;}
    constexpr Modint &operator++() noexcept {
        if (++x == MOD) x = 0;
        return *this;
    }
    constexpr Modint &operator--() noexcept {
        if (x-- == 0) x += MOD;
        return *this;
    }
    constexpr Modint operator++(int) noexcept {
        Modint res = *this;
        ++*this;
        return res;
    }
    constexpr Modint operator--(int) noexcept {
        Modint res = *this;
        --*this;
        return res;
    }
    constexpr Modint &operator+=(const Modint &y) noexcept {
        if ((x+=y.x) >= MOD) x -= MOD;
        return *this;
    }
    constexpr Modint &operator-=(const Modint &y) noexcept {
        if (x < y.x) x += MOD;
        x -= y.x;
        return *this;
    }
    constexpr Modint &operator*=(const Modint &y) noexcept {
        x = (unsigned long long)x*y.x%MOD;
        return *this;
    }
    constexpr Modint &operator/=(const Modint &y) noexcept {return *this*=y.inv();}
    friend constexpr Modint operator+(const Modint &l, const Modint &r) {return Modint(l)+=r;}
    friend constexpr Modint operator-(const Modint &l, const Modint &r) {return Modint(l)-=r;}
    friend constexpr Modint operator*(const Modint &l, const Modint &r) {return Modint(l)*=r;}
    friend constexpr Modint operator/(const Modint &l, const Modint &r) {return Modint(l)/=r;}
    friend constexpr bool operator==(const Modint &l, const Modint &r) {return l.x==r.x;}
    friend constexpr bool operator!=(const Modint &l, const Modint &r) {return l.x!=r.x;}
    friend constexpr istream &operator>>(istream &is, Modint &y) {
        long long z;
        y = (is>>z, z);
        return is;
    }
    friend constexpr ostream &operator<<(ostream &os, const Modint &y) {return os<<y.x;}
};

using mint = Modint<998244353>;

int N, M, K;
vector<int> G[5050];
mint dp[5050][5050];

void solve() {
    cin >> N >> M >> K;
    for (int i=0; i<M; i++) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dp[0][0] = 1;
    mint sum = 1;
    for (int i=0; i<K; i++) {
        fill(dp[i+1], dp[i+1]+N, sum);
        sum = 0;
        for (int j=0; j<N; j++) {
            for (int k: G[j]) dp[i+1][j] -= dp[i][k];
            dp[i+1][j] -= dp[i][j];
            sum += dp[i+1][j];
        }
    }
    cout << dp[K][0] << '\n';
}

signed main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    solve();
    return 0;
}