On his free time, Chouti likes doing some housework. He has got one new task, paint some bricks in the yard.

There are nn bricks lined in a row on the ground. Chouti has got mm paint buckets of different colors at hand, so he painted each brick in one of those mm colors.

Having finished painting all bricks, Chouti was satisfied. He stood back and decided to find something fun with these bricks. After some counting, he found there are kkbricks with a color different from the color of the brick on its left (the first brick is not counted, for sure).

So as usual, he needs your help in counting how many ways could he paint the bricks. Two ways of painting bricks are different if there is at least one brick painted in different colors in these two ways. Because the answer might be quite big, you only need to output the number of ways modulo 998244353998244353.

Input

The first and only line contains three integers nn, mm and kk (1≤n,m≤2000,0≤k≤n−11≤n,m≤2000,0≤k≤n−1) — the number of bricks, the number of colors, and the number of bricks, such that its color differs from the color of brick to the left of it.

Output

Print one integer — the number of ways to color bricks modulo 998244353998244353.

Examples

Input
3 3 0
Output
3
Input
3 2 1
Output
4

Note

In the first example, since k=0k=0, the color of every brick should be the same, so there will be exactly m=3m=3 ways to color the bricks.

In the second example, suppose the two colors in the buckets are yellow and lime, the following image shows all 44 possible colorings.

题意:

给你n个排成一列的方块,有m种颜色,让你求出这n个方块中有k个方块的颜色和左边的方块颜色不同的方案数量。

思路:

可以有两个方法来做这题,

我们先来看第一种方法,组合数学的方式,我们知道第一个方块是不会被计入到这k个数中的,所以无论如何排列,第一个方块都有m种取色的方案。

然后我们只需要在后面的n-1个方块中,选择k个,使之和左边的颜色不同,n-1中取k个,我们可以用组合数学的公式求出。

然后对于每一个被选择作为k个之一的方块,这个方块的唯一颜色限定就是要求和左边的颜色不同,而左边的颜色无论取什么,

对当前的方块来说只是一种取色,那么我们这个方块可以从除了左边的方块颜色中的m-1个颜色中任意选取一个。

而要求和左边颜色相同的方块,它们的颜色不不归属自己的选择,因为要和左边的颜色一样,

那么我们可以得到这题的公式,就是ans=m*C(n-1,k)* ((m-1)^k )

记得取模就好了。

方案1的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll n,m,k;
ll dp[2020][2020];
const ll mod=998244353ll;
ll quick(ll a,ll b,ll m)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=(a*ans)%m;
}
a=(a*a)%m;
b>>=1;
}
return ans;
}
ll inverse(ll a,ll p){return quick(a,p-2,p);} //模素数求逆元
// a 中选b个 ,结果对m取模
ll comp(ll a,ll b,ll m) //组合数取模
{
if(a<b) return 0;
if(a==b) return 1;
ll ans=1,ca=1,cb=1;
for(ll i=0;i<b;i++)
{
ca=(ca*(a-i))%m;
cb=(cb*(b-i))%m;
}
ans=(ca*inverse(cb,m))%m;
return ans;
}
int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
gbtb;
cin>>n>>m>>k;
ll ans=m;
ans=(ans+mod)%mod;
ans*=comp(n-1ll,k,mod);
ans=(ans+mod)%mod;
ans*=powmod(m-1ll,k,mod);
ans=(ans+mod)%mod;
// ans*=powmod(m,n-k,mod);
// ans=(ans+mod)%mod;
cout<<ans<<endl; return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

方案2:DP

我们定义二维DP的状态如下:

dp[i][j] 表示,到第i个位置时,有j个方块和左边的颜色不同的方案数。

我们再思考dp[i][j]这个状态可以从哪里转移过来。

我们考虑当前第i个位置的两种选择,

1,和左边相同的颜色。

那么应该加上上一个状态的j值,即  dp[i][j]+=dp[i-1][j]

2,和左边的值不相同,

那么当前的dp[i][j] 应该加上 dp[i-1][j-1]*(m-1)

即上一个状态,是j个不容方块时,乘上当前i块可以有m-1种取色。

最后的dp[n][k] 就是我们要得到的答案,

记得取模。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=;while(b){if(b%)ans=ans*a%MOD;a=a*a%MOD;b/=;}return ans;}
inline void getInt(int* p);
const int maxn=;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll n,m,k;
ll dp[][];
const ll mod=998244353ll; int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
gbtb;
cin>>n>>m>>k;
// dp[i][j] 到第i个位置,有k个和左边不同的
repd(i,,n)
{
dp[i][]=m;
}
repd(i,,n)
{
repd(j,,k)
{
dp[i][j]+=dp[i-][j];
dp[i][j]=(dp[i][j]+mod)%mod;
dp[i][j]+=dp[i-][j-]*(m-1ll);
dp[i][j]=(dp[i][j]+mod)%mod;
}
}
cout<<dp[n][k]<<endl; return ;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '');
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * - ch + '';
}
}
else {
*p = ch - '';
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * + ch - '';
}
}
}

Colorful Bricks CodeForces - 1081C ( 组合数学 或 DP )的更多相关文章

  1. Avito Cool Challenge 2018:C. Colorful Bricks

    C. Colorful Bricks 题目链接:https://codeforces.com/contest/1081/problem/C 题意: 有n个横向方块,一共有m种颜色,然后有k个方块的颜色 ...

  2. Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】

    传送门:http://codeforces.com/contest/1081/problem/C C. Colorful Bricks time limit per test 2 seconds me ...

  3. codeforces 1194F (组合数学)

    Codeforces 11194F (组合数学) 传送门:https://codeforces.com/contest/1194/problem/F 题意: 你有n个事件,你需要按照1~n的顺序完成这 ...

  4. 【bzoj5004】开锁魔法II 组合数学+概率dp

    题目描述 有 $n$ 个箱子,每个箱子里有且仅有一把钥匙,每个箱子有且仅有一把钥匙可以将其打开.现在随机打开 $m$ 个箱子,求能够将所有箱子打开的概率. 题解 组合数学+概率dp 题目约定了每个点的 ...

  5. [Codeforces 1201D]Treasure Hunting(DP)

    [Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...

  6. Codeforces - 1081C - Colorful Bricks - 简单dp - 组合数学

    https://codeforces.com/problemset/problem/1081/C 这道题是不会的,我只会考虑 $k=0$ 和 $k=1$ 的情况. $k=0$ 就是全部同色, $k=1 ...

  7. codeforces 932E Team Work(组合数学、dp)

    codeforces 932E Team Work 题意 给定 \(n(1e9)\).\(k(5000)\).求 \(\Sigma_{x=1}^{n}C_n^xx^k\). 题解 解法一 官方题解 的 ...

  8. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

  9. Codeforces 722E 组合数学 DP

    题意:有一个n * m的棋盘,你初始在点(1, 1),你需要去点(n, m).你初始有s分,在这个棋盘上有k个点,经过一次这个点分数就会变为s / 2(向上取整),问从起点到终点的分数的数学期望是多少 ...

随机推荐

  1. 使用 coverlet 查看.NET Core应用的测试覆盖率

    代码覆盖(Code coverage)是软件测试中的一种度量,描述程式中源代码被测试的比例和程度,所得比例称为代码覆盖率. Visual Studio 2017的企业版可以直接查看测试的代码覆盖率, ...

  2. python接口自动化(十)--post请求四种传送正文方式(详解)

    简介 post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先 ...

  3. C#利用NPOI操作Excel文件

    NPOI作为开源免费的组件,功能强大,可用来读写Excel(兼容xls和xlsx两种版本).Word.PPT文件.可是要让我们记住所有的操作,这便有点困难了,至此,总结一些在开发中常用的针对Excel ...

  4. commandArgument用于绑定一个传递的参数

    CommandArgument ='<%#Eval("spid")+","+Eval("piaohao")%>'

  5. 用v-bind:style时的问题

    今天纠结了挺久一个问题,个人习惯是在HBuilder里先写好前端样式,在放.net去测试数据,但是发现一个问题 就是一个提示框跟随鼠标移动 提示框用v-bind:style绑定一个对象 DIV就是这句 ...

  6. C# 合并、拆分PPT幻灯片

    概述 通过合并.拆分的功能,将不同的文档中的幻灯片进行组合形成新的的文档,同时也可以将一个多页的PPT文档按页拆分成多个不同的文档.此功能也丰富了编程人员对PPT幻灯片的操作的选择.下面将分别从以下几 ...

  7. Huffman Tree 简单构造

    //函数:构造Huffman树HT[2*n-1] #define MAXVALUE 9999//假设权值不超过9999 #define MAXLEAF 30 #define MAXNODE MAXLE ...

  8. 设计模式系列6:适配器模式(Adapter Pattern)

    定义 将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.    --<设计模式>GoF UML类图 使用场景 在遗留代码复用,类 ...

  9. Django之路由分发和反向解析

    一.路由分发: 路由分发是指:总路由不再直接做路由与视图函数的对应关系,而是将获取的路由分发给下面的app去处理对应关系 from django.conf.urls import url,includ ...

  10. C# 通用单例窗体类

    /// <summary> /// 通用的单例制作器 /// </summary> /// <typeparam name="T"></t ...