【codeforces1081C】 Colorful Bricks(DP 排列組合)

Description

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

There are n bricks lined in a row on the ground. Chouti has got m paint buckets of different colors at hand, so he painted each brick in one of those m 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 k bricks 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 998244353.

Input

The first and only line contains three integers n, m and k (1≤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 998244353
.

Sample Input

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

題意:n代表的有n個格子,m代表有m種顏色,k代表有k個格子的左邊第一個是與他不同的顏色

思路:
1.組合數學
因爲第一個格子不會影響其他的格子,所以第一個格子有m種顏色,從剩的n-1個格子中挑選k個,因爲這個格子與左邊的不同,所以這個格子能取的顏色是m-1種
所以公式爲
mCkn1(m1)km*C_k^{n-1}*(m-1)^k

Ckn1C_k^{n-1}遵循楊輝三角,即Cab=Ca1b+Ca1b1C_a^b=C_{a-1}^b+C_{a-1}^{b-1}

代碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <map>
#include<algorithm>
#define mod 998244353
#define memset(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
int c[2005][2005];
ll quick_pow(ll a, ll b)
{
    ll base = a,ans=1;
    while(b)
    {
        if(b & 1)
            ans = ((ans%mod) * (base%mod))%mod;
        base = ((base%mod)*(base%mod))%mod;
        b /= 2;
    }
    return ans;
}
int main()
{
    //init();
    ll n,m,k;
    memset(c,0);
    scanf("%lld %lld %lld",&n,&m,&k);
    ll ans;
    ll sum=quick_pow(m-1,k);
    for(int i=1; i<=2000; i++)
        for(int j=0; j<=2000; j++)
        {
            if(j == 1)
                c[i][j] = i;
            else if(j == 0)
                c[i][j] = 1;
            else
                c[i][j] = (c[i-1][j]+c[i-1][j-1])%mod;
        }

      //cout<<c[5]<<endl;
      ll sum2;
      if(k == 0)
        sum2 = 1;
      else
       sum2 = c[n-1][k];
    ans = (((m * sum)%mod)*sum2)%mod;
    printf("%lld\n",ans%mod);

    return 0;
}

2.DP
dp[ i ][ j ]代表一共有i個格子,j個符合條件的
所以狀態轉移方程爲:
dp[ i ][ j ] = dp[ i-1 ][ j ] + dp[ i-1 ][ j-1 ]*(m-1)

代碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <map>
#include<algorithm>
#define mod 998244353
#define memset(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
ll dp[2005][2005];
int main()
{
    //init();
    int n,m,k;
    memset(dp,0);
    scanf("%d %d %d",&n,&m,&k);
    dp[1][0] = 1;
    for(int i=1; i<=2000; i++)
        for(int j=0; j<=2000; j++)
        {
            if(j == 0)
                dp[i][j] = m;
            else
                dp[i][j] = (dp[i-1][j]%mod + ((dp[i-1][j-1]%mod)*(m-1))%mod)%mod;
        }

    printf("%lld\n",dp[n][k]);

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章