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 C# (.NET Core 3.1.201) (judge verdict: Time Limit Exceeded)

using System;
using static System.Console;

namespace abc167
{
    class Program
    {
        const int keyNum = 998244353;
        static void Main()
        {
            var nmk = ReadLine().Split(' ');
            var n = int.Parse(nmk[0]);
            var m = int.Parse(nmk[1]);
            var k = int.Parse(nmk[2]);

            int[] facts = null;
            int[] revFacts = null;
            var mongomery = new Mongomery(keyNum);
            GetFactorialsDiv(n, keyNum, mongomery, out facts, out revFacts);

            var total = 0L;
            for (var i = 0; i <= k; ++i)
            {
                var subTotal = ((long)NCRDiv(n - 1, i, facts, revFacts, keyNum) * m) % keyNum;
                for (var j = 1; j < n - i; ++j)
                {
                    subTotal = (subTotal * (m - 1)) % keyNum;
                }
                total = (total + subTotal) % keyNum;
            }
            WriteLine(total);
        }

        static void GetFactorialsDiv(int n, int keyNum, Mongomery m, out int[] facts, out int[] revFacts)
        {
            facts = new int[n + 1];
            revFacts = new int[n + 1];

            facts[0] = 1;
            long tmp = 1;
            for (var i = 1; i <= n; ++i)
            {
                tmp = m.Mul(tmp, i);
                facts[i] = (int)tmp;
            }
            // n!^-1 = n!^(m-2) (mod m)
            tmp = m.Exp(facts[n], keyNum - 2);
            revFacts[n] = (int)tmp;
            for (var i = n; i > 1; --i)
            {
                tmp = m.Mul(tmp, i);
                revFacts[i - 1] = (int)tmp;
            }
        }
        static int NCRDiv(int n, int r, int[] facts, int[] revFacts, int keyNum)
        {
            if (r == 0)
            {
                return 1;
            }
            if (r == 1)
            {
                return n;
            }
            var result = 1L;
            result = (result * facts[n]) % keyNum;
            result = (result * revFacts[r]) % keyNum;
            result = (result * revFacts[n - r]) % keyNum;
            return (int)result;
        }
        class Mongomery
        {
            int n;
            int nBits;
            long r2;
            int mask;
            long nr;
            public Mongomery(int n)
            {
                this.n = n;
                var tmp = 1;
                nBits = 1;
                while (true)
                {
                    if (tmp >= n)
                    {
                        break;
                    }
                    tmp = tmp * 2;
                    ++nBits;
                }
                r2 = (1L << (nBits * 2)) % n;
                mask = (1 << nBits) - 1;

                nr = 0;
                var t = 0;
                var vi = 1;
                for (var i = 0; i < nBits; ++i)
                {
                    if ((t & 1) == 0)
                    {
                        t += n;
                        nr += vi;
                    }
                    t >>= 1;
                    vi <<= 1;
                }
            }
            public int Reduction(long t)
            {
                var c = t * nr;
                c &= mask;
                c *= n;
                c += t;
                c >>= nBits;
                if (c >= n)
                {
                    c -= n;
                }
                return (int)c;
            }
            public int Mul(long a, int b)
            {
                return Reduction(Reduction(a * b) * r2);
            }
            public int Exp(int a, int b)
            {
                var p = Reduction((long)a * r2);
                var x = Reduction(r2);
                var y = b;
                while (y > 0)
                {
                    if ((y & 1) == 1)
                    {
                        x = Reduction((long)x * p);
                    }
                    p = Reduction((long)p * p);
                    y >>= 1;
                }
                return Reduction(x);
            }
        }
    }
}