在这里插入图片描述

状态表示

  • f[I][j]: 考虑到第i 并且收益为j 的方案数
  • 收益是指: 移动后比移动前不同的数是多少
  • 收益可以为负数,下标整体偏移2000 // 最大情况就是2000
  • 初使化f【0】【0】=1
  • 状态转移
    * 当a[I]==a[I+1] ,考虑第i个字符 k 个字符都可以,收益不变
    * 其他情况 :f[i][j] ,是有哪些状态转移过来的,首先 考虑第i个字符时,代价可以+1(填a[i+1]) 代价可以-1(填a[i]),代价可以不变,填除了a[i],a[i+1]的情况

代码

#include <iostream>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
using ll = long long;
const int MAXN = 2005;
const int MOD = 998244353;
ll dp[MAXN][MAXN<<1],h[MAXN];

int main()
{
    SIS;
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++) cin >> h[i];
    if(k==1)
    {
        cout << 0 << endl;
        return 0;
    }
    dp[0][2000]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<MAXN<<1;j++)
            if(h[i]==h[i%n+1]) dp[i][j]=(dp[i-1][j]*k)%MOD;
            else dp[i][j]=(dp[i-1][j-1]+dp[i-1][j+1]+dp[i-1][j]*(k-2))%MOD;
    ll ans=0;
    for(int i=1;i<=n;i++)
        ans=(ans+dp[n][2000+i])%MOD;
    cout << ans << endl;
    return 0;
}
 posted on 2020-03-07 15:04  谁是凶手1703  阅读(60)  评论(0)    收藏  举报