Problem p02685 (C++)

Buggy submission (status: Runtime Error):
#ifdef DEBUG

#else

#pragma GCC optimize("O3,no-stack-protector")
#pragma GCC optimize("unroll-loops")

#if __cplusplus < 201703L
#pragma GCC target("avx")
#else
#pragma GCC target("avx2")
#endif

#endif
// 実数の場合
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define dump(x) cout << x << endl
typedef int64_t Int;
typedef long double Ld;

using namespace std;
using Graph = vector<vector<Int>>;

const double pi = M_PI;
const Int MOD = 998244353;

// 二分累乗法
template <typename T> T modpow(T a, T n, T mod) {
  T ret = 1;

  if (mod == 1) {
    while (n > 0) {
      if (n & 1) {
        ret = ret * a;
      }
      a = a * a;
      n >>= 1;
    }
  } else {
    while (n > 0) {
      if (n & 1) {
        ret = ret * a % mod;
      }
      a = a * a % mod;
      n >>= 1;
    }
  }

  return ret;
}

vector<Int> factorials, invs;
bool is_ncr_table = false;
// modが素数の場合のみ
void calc_ncr_table(Int n, Int mod) {
  is_ncr_table = true;

  // 1! ~ n! の計算
  Int f = 1;
  factorials.push_back(f);
  for (Int i = 1; i <= n; i++) {
    f *= i;
    f %= mod;
    factorials.push_back(f);
  }

  // n!^-1 の計算
  Int inv = modpow(factorials[n], mod - 2, mod);
  // (n-1)!^-1 ~ 1!^-1 の計算
  invs.assign(n, 1);
  invs[n] = inv;
  for (Int i = n; i >= 1; i--) {
    inv *= i;
    inv %= mod;
    invs[i - 1] = inv;
  }
}

// 一度だけnCrを計算するとき用の関数
Int factorial(Int n, Int mod = 1) {
  Int ret = 1;
  if (mod == 1) {
    for (Int i = 1; i <= n; i++) {
      ret *= i;
    }

    return ret;
  } else {
    for (Int i = 1; i <= n; i++) {
      ret *= i;
      ret %= mod;
    }

    return ret;
  }
}

Int ncr(Int n, Int r, Int mod) {
  if (n < r) {
    return (Int)0;
  } else {
    if (is_ncr_table) {
      // modが素数の場合のみ
      return (factorials[n] * invs[r] % mod) * invs[n - r] % mod;
    } else {
      Int x = 1;
      for (Int i = n - r + 1; i <= n; i++) {
        x *= i;
        x %= mod;
      }
      return x * modpow(factorial(r, mod), mod - 2, mod) % mod;
    }
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  Int n, m, k;
  cin >> n >> m >> k;

  calc_ncr_table(n, MOD);

  Int ans = 0;
  for (Int i = k; i >= 0; --i) {
    Int a, b, c;
    a = m;
    b = ncr(n - 1, n - i - 1, MOD);
    c = modpow(m - 1, n - 1 - i, MOD);
    a = (a * b) % MOD;
    a = (a * c) % MOD;
    ans = (ans + a) % MOD;
  }

  cout << ans << endl;

  return 0;
}

Fixed submission:
#ifdef DEBUG

#else

#pragma GCC optimize("O3,no-stack-protector")
#pragma GCC optimize("unroll-loops")

#if __cplusplus < 201703L
#pragma GCC target("avx")
#else
#pragma GCC target("avx2")
#endif

#endif
// 実数の場合
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
#define dump(x) cout << x << endl
typedef int64_t Int;
typedef long double Ld;

using namespace std;
using Graph = vector<vector<Int>>;

const double pi = M_PI;
const Int MOD = 998244353;

// 二分累乗法
template <typename T> T modpow(T a, T n, T mod) {
  T ret = 1;

  if (mod == 1) {
    while (n > 0) {
      if (n & 1) {
        ret = ret * a;
      }
      a = a * a;
      n >>= 1;
    }
  } else {
    while (n > 0) {
      if (n & 1) {
        ret = ret * a % mod;
      }
      a = a * a % mod;
      n >>= 1;
    }
  }

  return ret;
}

vector<Int> factorials, invs;
bool is_ncr_table = false;
// modが素数の場合のみ
void calc_ncr_table(Int n, Int mod) {
  is_ncr_table = true;

  // 1! ~ n! の計算
  Int f = 1;
  factorials.push_back(f);
  for (Int i = 1; i <= n; i++) {
    f *= i;
    f %= mod;
    factorials.push_back(f);
  }

  // n!^-1 の計算
  Int inv = modpow(factorials[n], mod - 2, mod);
  // (n-1)!^-1 ~ 1!^-1 の計算
  invs.assign(n + 1, 1);
  invs[n] = inv;
  for (Int i = n; i >= 1; i--) {
    inv *= i;
    inv %= mod;
    invs[i - 1] = inv;
  }
}

// 一度だけnCrを計算するとき用の関数
Int factorial(Int n, Int mod = 1) {
  Int ret = 1;
  if (mod == 1) {
    for (Int i = 1; i <= n; i++) {
      ret *= i;
    }

    return ret;
  } else {
    for (Int i = 1; i <= n; i++) {
      ret *= i;
      ret %= mod;
    }

    return ret;
  }
}

Int ncr(Int n, Int r, Int mod) {
  if (n < r) {
    return (Int)0;
  } else {
    if (is_ncr_table) {
      // modが素数の場合のみ
      return (factorials[n] * invs[r] % mod) * invs[n - r] % mod;
    } else {
      Int x = 1;
      for (Int i = n - r + 1; i <= n; i++) {
        x *= i;
        x %= mod;
      }
      return x * modpow(factorial(r, mod), mod - 2, mod) % mod;
    }
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  Int n, m, k;
  cin >> n >> m >> k;

  calc_ncr_table(n, MOD);

  Int ans = 0;
  for (Int i = k; i >= 0; --i) {
    Int a, b, c;
    a = m;
    b = ncr(n - 1, n - i - 1, MOD);
    c = modpow(m - 1, n - 1 - i, MOD);
    a = (a * b) % MOD;
    a = (a * c) % MOD;
    ans = (ans + a) % MOD;
  }

  cout << ans << endl;

  return 0;
}