Problem:
Score : 500 points

Problem Statement

There are N blocks arranged in a row. Let us paint these blocks.

We will consider two ways to paint the blocks different if and only if there is a block painted in different colors in those two ways.

Find the number of ways to paint the blocks under the following conditions:

For each block, use one of the M colors, Color 1 through Color M, to paint it. It is not mandatory to use all the colors.

There may be at most K pairs of adjacent blocks that are painted in the same color.

Since the count may be enormous, print it modulo 998244353.

Constraints

All values in input are integers.

1 \leq N, M \leq 2 \times 10^5

0 \leq K \leq N - 1

Input

Input is given from Standard Input in the following format:

N M K

Output

Print the answer.

Sample Input 1

3 2 1

Sample Output 1

6

The following ways to paint the blocks satisfy the conditions: 112, 121, 122, 211, 212, and 221. Here, digits represent the colors of the blocks.

Sample Input 2

100 100 0

Sample Output 2

73074801

Sample Input 3

60522 114575 7559

Sample Output 3

479519525

Solution in Rust (1.42.0) (judge verdict: Accepted)

use proconio::*;

#[warn(non_snake_case)]
fn main() {
    input!(n: usize, m: usize, k: usize);
    let mut ans = Mod::new(0);
    let M = ModConb::new(2 * n);
    for x in 0..n {
        let a = Mod::new(m);
        let b = Mod::new(m - 1).pow(n - x - 1);
        let c = M.get(n - 1, x);
        let t = a * b * c;
        if x <= k {
            ans = ans + t;
        }
    }

    println!("{}", ans.unwrap());
}

const MOD: usize = 998_244_353;

#[warn(dead_code)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
struct Mod {
    val: usize,
}

// 和を定義
impl std::ops::Add for Mod {
    type Output = Mod;
    // O(1)
    fn add(self, other: Mod) -> Mod {
        Mod {
            val: (self.val + other.val) % MOD,
        }
    }
}

// 差を定義
impl std::ops::Sub for Mod {
    type Output = Mod;

    // O(1)
    fn sub(self, other: Mod) -> Mod {
        Mod {
            val: (self.val + MOD - other.val) % MOD,
        }
    }
}

// 積を定義
impl std::ops::Mul for Mod {
    type Output = Mod;

    // O(1)
    fn mul(self, other: Mod) -> Mod {
        Mod {
            val: (self.val * other.val) % MOD,
        }
    }
}

// 加法単位元
impl std::ops::Neg for Mod {
    type Output = Mod;

    // O(1)
    fn neg(self) -> Mod {
        Mod {
            val: MOD - self.val,
        }
    }
}

// 逆元を定義
// フェルマーの小定理により実装
impl std::ops::Div for Mod {
    type Output = Mod;

    //O(logN)
    fn div(self, other: Mod) -> Mod {
        self * other.inv()
    }
}

impl Mod {
    // コンストラクター
    fn new(n: usize) -> Mod {
        Mod { val: n % MOD }
    }

    // 加法単位元
    fn new_zero() -> Mod {
        Mod { val: 0 }
    }

    // 乗法単位元
    fn new_one() -> Mod {
        Mod { val: 1 }
    }

    // 加法逆元
    // 上記にて定義

    // 乗法逆元
    fn inv(self) -> Mod {
        if self.val == 0 {
            panic!("zero divide");
        }
        self.pow(MOD - 2)
    }

    // 累乗を定義
    // O(logN)
    fn pow(self, n: usize) -> Mod {
        let mut res = 1;
        let mut a = self.unwrap();
        let mut n = n;

        while n > 0 {
            if n % 2 == 0 {
                a = a * a;
                n /= 2;
            } else {
                res = res * a;
                a = a * a;
                n /= 2;
            }
            res %= MOD;
            a %= MOD;
        }
        Mod::new(res)
    }

    // 最大公約数
    // O(logN)
    fn gcd(self, other: Mod) -> usize {
        let mut x = self.val;
        let mut y = other.val;
        while y != 0 {
            let t = y;
            y = x % y;
            x = t;
        }
        x
    }

    // 階乗
    // O(N)
    fn fact(self) -> Mod {
        let mut res = 1;
        for i in 1..self.val + 1 {
            res *= i;
            res %= MOD;
        }

        Mod::new(res)
    }

    // 順列
    fn perm(self, other: Mod) -> Mod {
        let mut res = Mod::new_one();
        for x in (self.val - other.val + 1)..self.val + 1 {
            res = res * Mod::new(x);
        }

        res
    }

    // 組み合わせ O(N)
    fn conb(self, other: Mod) -> Mod {
        if self < other {
            return Mod::new_zero();
        }
        self.fact() / (other.fact() * (self - other).fact())
    }
    fn unwrap(self) -> usize {
        self.val % MOD
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
struct ModConb {
    fact: Vec<Mod>,
    inv_fact: Vec<Mod>,
    n: usize,
}

impl ModConb {
    // O(N)
    fn new(n: usize) -> ModConb {
        let mut fact = vec![Mod::new_one(); n + 1];
        let mut inv_fact = vec![Mod::new_one(); n + 1];
        for i in 1..(n + 1) {
            fact[i] = fact[i - 1] * Mod::new(i);
            inv_fact[i] = inv_fact[i - 1] / Mod::new(i);
        }

        ModConb {
            fact,
            inv_fact,
            n: n + 1,
        }
    }
    // O(1)
    fn get(&self, n: usize, r: usize) -> Mod {
        if r <= n {
            self.fact[n] * self.inv_fact[r] * self.inv_fact[n - r]
        } else {
            Mod::new_zero()
        }
    }
}