【codeforces 17C】Balance

題目:Balance

題意:

       計數類DP。

       給出一個長度爲n的只由a,b,c組成的字符串,每次操作可以把一個字母變成其相鄰的某個字母,定義一個字符串是平衡的當且僅當三個字母出現的次數相差不超過1,問這個字符串經過若干次操作可以變成多少個不同的平衡的字符串。

解析:

       參見CodeForces 17 C.Balance(dp)

       重點在於變化前後連續段之間的有序性(或者說相對位置)是不變的,所以只要保證枚舉完所有的段,就可以保證不重不漏。

 

代碼:

#include <bits/stdc++.h>
using namespace std;

const int mod=51123987;
int n,m,ans;
int now[3],f[155][55][55][55],nxt[155][3];
char ch[155];

inline bool check(int i,int j,int k)
{
	return (i+j+k==n&&abs(i-j)<=1&&abs(i-k)<=1&&abs(j-k)<=1);
}
inline void add(int &a,int b)
{
	a=(a+b)>=mod?(a+b)%mod:a+b;
}

int main()
{
	scanf("%d%s",&n,ch+1),m=n/3+1;
	for(int i=n;i;i--)
	{
	  now[ch[i]-'a']=i;
	  for(int j=0;j<3;j++) nxt[i][j]=now[j];
	}
	f[1][0][0][0]=1;
	for(int p=1;p<=n;p++)
	  for(int i=0;i<=m;i++)
	    for(int j=0;j<=m;j++)
	      for(int k=0;k<=m;k++)
	      {
	      	if(check(i,j,k)) add(ans,f[p][i][j][k]);
	      	if(nxt[p][0]) add(f[nxt[p][0]][i+1][j][k],f[p][i][j][k]);
	      	if(nxt[p][1]) add(f[nxt[p][1]][i][j+1][k],f[p][i][j][k]);
	      	if(nxt[p][2]) add(f[nxt[p][2]][i][j][k+1],f[p][i][j][k]);
	      }
	cout<<ans;
	return 0;
}

 

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