我們先DP分析
dp[i][j]表示,按從左往右的順序填到i時,有j對相鄰數字不同,的方案數
顯然:dp[i][j]=dp[i-1][j]*(m-1)+dp[i-1][j-1];
我們把DP在紙上推演如下:
發現:每個i所在行的d[pi][j]其實就是二次項展開的一項
求和dp[n][0]到dp[n][k]即可。
第二種思路是用組合數直接進行分析:
考慮:n個數,k個相鄰位置數相同,
我們在n-1個空位中選擇k個位置,使得k左右數相同。
然後固定最左邊的數,有m種選法,依次往右選,遇到剛纔選出的位置,選法只有一種。
其餘都是m-1種選法。
綜上方案數爲:
同樣求和即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 2e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/
const int mod = 998244353;
ll qpow (ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll fac[M],inv[M],p[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
ll n,m,k;
cin>>n>>m>>k;
fac[0]=p[0]=inv[0]=1;
for(int i=1;i<=200000;i++)fac[i]=fac[i-1]*i%mod,p[i]=p[i-1]*(m-1)%mod;;
inv[200000]=qpow(fac[200000],mod-2);
for(int i=200000-1;i;i--)inv[i]=inv[i+1]*(i+1)%mod;
ll ans=0;
for(int i=1;i<=k;i++)
{
ll C=fac[n-1]*inv[i]%mod*inv[n-1-i]%mod;
ans=(ans+m*p[n-i-1]%mod*C%mod)%mod;
}
ans=(ans+m*p[n-1]%mod)%mod;
cout<<ans<<endl;
return 0;
}