题目链接:这里
题意:你可以使得一个元素变成他周围的元素的颜色,可以改变无数次,现在给你一个串,问你一共有多少种方案,使得a和b和c的个数相差不超过1。
题解:dp[i][a][b][c],表示考虑到第i个位置,当前有a个a,b个b,c个c 的方案数
然后转移就好了
维护一个next[i][3]表示下一个在哪儿。
虽然是4维dp,但是却是150 50 50 50 的

//CF 17C
#include <bits/stdc++.h>
using namespace std;
const int mod = 51123987;
int n, dp[152][52][52][52], nxt[152][3];
void add(int &x, int y){
    x = x + y;
    if(x>=mod) x%=mod;
}
int main()
{
    scanf("%d", &n);
    string s;
    cin >> s;
    for(int j = 0; j < 3; j++) nxt[n][j] = n;
    for(int i = n - 1; i >= 0; i--){
        for(int j = 0; j < 3; j++){
            nxt[i][j] = nxt[i+1][j];
        }
        nxt[i][s[i]-'a'] = i;
    }
    dp[0][0][0][0] = 1;
    int ans = 0;
    for(int i = 0; i < n; i++){
        for(int a = 0; a*3 <= n+2; a++){
            for(int b = 0; b*3 <= n+2; b++){
                for(int c = 0; c*3 <= n+2 && a+b+c<=n; c++){
                    if(dp[i][a][b][c]){
                        if(a+b+c==n&&abs(a-c)<=1&&abs(b-c)<=1&&abs(a-c)<=1) add(ans, dp[i][a][b][c]);
                        add(dp[nxt[i][0]][a+1][b][c], dp[i][a][b][c]);
                        add(dp[nxt[i][1]][a][b+1][c], dp[i][a][b][c]);
                        add(dp[nxt[i][2]][a][b][c+1], dp[i][a][b][c]);
                    }
                }
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}