#![allow(dead_code)]
use crate::modulo::*;
use crate::nums::Comb;
use crate::scanner::Scanner;
modint!(998244353);
fn main() {
    let mut scan = Scanner::new();
    let n = scan.read::<i64>();
    let m = scan.read::<i64>();
    let k = scan.read::<i64>();
    let mut ret = Z::new(0);
    let comb = Comb::new(n as usize);
    for j in 0..=k {
        ret += Z::new(m) * comb.of(n as usize - 1, j as usize) * Z::new(m - 1).pow(n - 1 - j);
    }
    println!("{}", ret);
}
mod nums {
    use crate::modint;
    use crate::modulo::ConstValue;
    use crate::modulo::ModInt;
    pub fn gcd(a: i64, b: i64) -> i64 {
        if b == 0 {
            a
        } else {
            gcd(b, a % b)
        }
    }
    pub fn lcm(a: i64, b: i64) -> i64 {
        a / gcd(a, b) * b
    }
    pub fn extgcd(a: i64, b: i64) -> (i64, i64, i64) {
        if b == 0 {
            (a, 1, 0)
        } else {
            let (gcd, x, y) = extgcd(b, a % b);
            (gcd, y, x - (a / b) * y)
        }
    }
    pub fn modinv_extgcd(m: i64, a_: i64) -> i64 {
        let mut a = a_ as i64;
        let mut b = m as i64;
        let mut u = 1;
        let mut v = 0;
        while b != 0 {
            let t = a / b;
            a -= t * b;
            std::mem::swap(&mut a, &mut b);
            u -= t * v;
            std::mem::swap(&mut u, &mut v);
        }
        u %= m;
        if u < 0 {
            u += m
        };
        u as i64
    }
    pub fn pascal(n: usize) -> Vec<Vec<i64>> {
        let mut comb = vec![vec![0i64; n + 1]; n + 1];
        for i in 0..n + 1 {
            comb[i][0] = 1;
            comb[i][i] = 1;
        }
        for i in 2..n + 1 {
            for j in 1..i {
                comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
            }
        }
        comb
    }
    pub struct Comb<T> {
        fact: Vec<ModInt<T>>,
        ifact: Vec<ModInt<T>>,
    }
    impl<T: ConstValue> Comb<T> {
        pub fn new(n: usize) -> Self {
            let mut fact = vec![ModInt::<T>::new(0); n + 1];
            let mut ifact = vec![ModInt::<T>::new(0); n + 1];
            fact[0] = ModInt::<T>::new(1);
            for i in 1..=n {
                fact[i] = fact[i - 1] * i.into();
            }
            ifact[n] = fact[n].inv();
            for i in (1..=n).rev() {
                ifact[i - 1] = ifact[i] * i.into();
            }
            Comb { fact, ifact }
        }
        pub fn of(&self, n: usize, k: usize) -> ModInt<T> {
            if n < k {
                0i64.into()
            } else {
                self.fact[n] * self.ifact[k] * self.ifact[n - k]
            }
        }
        #[doc = " combination with repetition"]
        pub fn rep(&self, n: usize, k: usize) -> ModInt<T> {
            self.of(n + k - 1, k)
        }
        pub fn perm(&self, n: usize, k: usize) -> ModInt<T> {
            if n < k {
                0i64.into()
            } else {
                self.fact[n] * self.ifact[n - k]
            }
        }
    }
    pub fn comb<T: ConstValue>(n: i64, r: i64) -> ModInt<T> {
        let mut ret: ModInt<T> = ModInt::new(1);
        for i in 0..r {
            ret *= ModInt::new(n - i);
            ret /= ModInt::new(i + 1);
        }
        ret
    }
    pub fn comb_series<T: ConstValue>(n: i64, k: i64) -> impl Iterator<Item = ModInt<T>> {
        (0..=k).scan(ModInt::<T>::new(1), move |comb, i| {
            let ret = *comb;
            *comb = *comb * ModInt::new(n - i) / ModInt::new(i + 1);
            Some(ret)
        })
    }
    pub fn comb_series_incr<T: ConstValue>(n: i64, k: i64) -> impl Iterator<Item = ModInt<T>> {
        (0..=k).scan(ModInt::<T>::new(1), move |comb, i| {
            let ret = *comb;
            *comb = *comb * ModInt::new(n + i + 1) / ModInt::new(i + 1);
            Some(ret)
        })
    }
    pub fn dot(a: &[i64], b: &[i64]) -> i64 {
        let mut c = 0;
        for i in 0..a.len() {
            c += a[i] * b[i];
        }
        c
    }
    pub fn cross(a: &[i64], b: &[i64]) -> i64 {
        a[0] * b[1] - a[1] * b[0]
    }
    pub fn matrix_mul(a: &[Vec<i64>], b: &[Vec<i64>]) -> Vec<Vec<i64>> {
        let mut c = vec![vec![0; b[0].len()]; a.len()];
        for i in 0..a.len() {
            for k in 0..b.len() {
                for j in 0..b[0].len() {
                    c[i][j] = c[i][j] + a[i][k] * b[k][j];
                }
            }
        }
        c
    }
    pub fn matrix_pow(a_: &[Vec<i64>], mut n: i64) -> Vec<Vec<i64>> {
        let mut a: Vec<Vec<i64>> = a_.to_vec();
        let mut b = vec![vec![0; a.len()]; a.len()];
        for i in 0..a.len() {
            b[i][i] = 1;
        }
        while n > 0 {
            if n & 1 == 1 {
                b = matrix_mul(&b, &a);
            }
            a = matrix_mul(&a, &a);
            n >>= 1;
        }
        b
    }
    pub fn ceil_div(x: i64, y: i64) -> i64 {
        (x + y - 1) / y
    }
    modint!(997);
}
mod modulo {
    use crate::tiny_num_traits::ZeroOne;
    use std::marker::PhantomData;
    use std::ops::*;
    #[derive(Debug, PartialEq, Copy, Clone)]
    pub struct ModInt<T>(pub i64, PhantomData<*const T>);
    impl<T: ConstValue> ModInt<T> {
        pub fn new<U: ModIntCastable>(a: U) -> ModInt<T> {
            ModInt((a.to_long() % T::M + T::M) % T::M, PhantomData)
        }
        pub fn pow(self, mut n: i64) -> Self {
            let mut a = self;
            let mut res = Self::new(1);
            while n > 0 {
                if n & 1 == 1 {
                    res *= a;
                }
                a = a * a;
                n >>= 1;
            }
            res
        }
        pub fn inv(self) -> Self {
            self.pow(T::M - 2)
        }
    }
    pub trait ConstValue: Clone + Copy {
        const M: i64;
    }
    impl<T> std::fmt::Display for ModInt<T> {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
            write!(f, "{}", self.0)
        }
    }
    impl<T: ConstValue, U: ModIntCastable> From<U> for ModInt<T> {
        fn from(n: U) -> Self {
            Self::new(n)
        }
    }
    impl<T: ConstValue> Add for ModInt<T> {
        type Output = ModInt<T>;
        fn add(self, other: ModInt<T>) -> ModInt<T> {
            Self::new(self.0 + other.0)
        }
    }
    impl<T: ConstValue> AddAssign for ModInt<T> {
        fn add_assign(&mut self, other: Self) {
            *self = self.add(other);
        }
    }
    impl<T: ConstValue> Sub for ModInt<T> {
        type Output = ModInt<T>;
        fn sub(self, other: ModInt<T>) -> ModInt<T> {
            Self::new(self.0 - other.0)
        }
    }
    impl<T: ConstValue> SubAssign for ModInt<T> {
        fn sub_assign(&mut self, other: Self) {
            *self = self.sub(other);
        }
    }
    impl<T: ConstValue> Mul for ModInt<T> {
        type Output = ModInt<T>;
        fn mul(self, other: ModInt<T>) -> ModInt<T> {
            Self::new(self.0 * other.0)
        }
    }
    impl<T: ConstValue> MulAssign for ModInt<T> {
        fn mul_assign(&mut self, other: Self) {
            *self = self.mul(other);
        }
    }
    impl<T: ConstValue> Div for ModInt<T> {
        type Output = ModInt<T>;
        fn div(self, other: ModInt<T>) -> ModInt<T> {
            self * other.inv()
        }
    }
    impl<T: ConstValue> DivAssign for ModInt<T> {
        fn div_assign(&mut self, other: Self) {
            *self = self.div(other);
        }
    }
    #[macro_export]
    macro_rules! modint {
        ( $ m : expr ) => {
            #[derive(Debug, PartialEq, Copy, Clone)]
            pub enum __M {}
            impl ConstValue for __M {
                const M: i64 = $m;
            }
            #[allow(dead_code)]
            type Z = ModInt<__M>;
        };
    }
    pub trait ModIntCastable {
        fn to_long(self) -> i64;
    }
    impl ModIntCastable for i64 {
        fn to_long(self) -> i64 {
            self
        }
    }
    impl ModIntCastable for usize {
        fn to_long(self) -> i64 {
            self as i64
        }
    }
    impl ModIntCastable for i32 {
        fn to_long(self) -> i64 {
            self as i64
        }
    }
    impl<T: ConstValue> ZeroOne for ModInt<T> {
        fn zero() -> Self {
            Self::new(0)
        }
        fn one() -> Self {
            Self::new(1)
        }
    }
}
mod scanner {
    use std::io::{stdin, BufReader, Bytes, Read, Stdin};
    use std::str::FromStr;
    pub struct Scanner {
        buf: Bytes<BufReader<Stdin>>,
    }
    impl Scanner {
        pub fn new() -> Scanner {
            Scanner {
                buf: BufReader::new(stdin()).bytes(),
            }
        }
        pub fn read_next<T: FromStr>(&mut self) -> Option<T> {
            let token = self
                .buf
                .by_ref()
                .map(|c| c.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect::<String>();
            token.parse::<T>().ok()
        }
        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_next().unwrap()
        }
        pub fn readn<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read::<T>()).collect()
        }
        pub fn chars(&mut self) -> Vec<char> {
            self.read::<String>().chars().collect()
        }
    }
}
mod tiny_num_traits {
    pub trait ZeroOne {
        fn zero() -> Self;
        fn one() -> Self;
    }
    macro_rules! impl_zero_one {
        ( $ tpe : ident ) => {
            impl ZeroOne for $tpe {
                fn zero() -> Self {
                    0
                }
                fn one() -> Self {
                    1
                }
            }
        };
    }
    impl_zero_one!(i64);
    impl_zero_one!(i32);
    impl_zero_one!(usize);
}



Measured memory_bytes: 5116