Codeforces Beta Round #17 C. Balance DP

转自:http://www.cnblogs.com/qscqesze/p/6173531.html

C. Balance
题目链接

http://codeforces.com/contest/17/problem/C
题面

Nick likes strings very much, he likes to rotate them, sort them, rearrange characters within a string… Once he wrote a random string of characters a, b, c on a piece of paper and began to perform the following operations:

to take two adjacent characters and replace the second character with the first one,
to take two adjacent characters and replace the first character with the second one
To understand these actions better, let’s take a look at a string «abc». All of the following strings can be obtained by performing one of the described operations on «abc»: «bbc», «abb», «acc». Let’s denote the frequency of a character for each of the characters a, b and c as the number of occurrences of this character in the string. For example, for string «abc»: |a| = 1, |b| = 1, |c| = 1, and for string «bbc»: |a| = 0, |b| = 2, |c| = 1.

While performing the described operations, Nick sometimes got balanced strings. Let’s say that a string is balanced, if the frequencies of each character differ by at most 1. That is  - 1 ≤ |a| - |b| ≤ 1,  - 1 ≤ |a| - |c| ≤ 1 и  - 1 ≤ |b| - |c| ≤ 1.

Would you help Nick find the number of different balanced strings that can be obtained by performing the operations described above, perhaps multiple times, on the given string s. This number should be calculated modulo 51123987.
输入

The first line contains integer n (1 ≤ n ≤ 150) — the length of the given string s. Next line contains the given string s. The initial string can be balanced as well, in this case it should be counted too. The given string s consists only of characters a, b and c.
输出

Output the only number — the number of different balanced strings that can be obtained by performing the described operations, perhaps multiple times, on the given string s, modulo 51123987.
样例输入

4
abca
样例输出

7
题意

你可以使得一个元素变成他周围的元素的颜色,可以改变无数次,现在给你一个串,问你一共有多少种方案,使得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 的

#include<bits/stdc++.h>
using namespace std;
const int mod = 51123987;
int dp[152][52][52][52],n,nxt[152][3];
string s;
void add(int &a,int b){
    a = a+b;
    if(a>=mod)a%=mod;
}
int main()
{
    scanf("%d",&n);
    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(b-c)<=1&&abs(a-c)<=1&&abs(b-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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值