arc089F - ColoringBalls

题目大意


题解

半想半看myh的做法

官方题解是暴力枚举划分然后算,因为n和k很小所以跑得很快

首先有一个结论:一段有d个连续b段的染色结果是由rb+(d-1)个r或b所造成的

证明考虑归纳,首先d=1的时候成立,然后每加上一个b就把第一段b去掉,剩下的是d-1的情况;如哦加上一个r就考虑把第一段的b一分为二,根据归纳也可以保证第一个出现的b在最左边

然后可以考虑dp,先枚举rb的段数x和r的段数y

一开始想的是n^6log的做法,即设f[i,j,k]表示放了i段总和为j当前最短的一段为k,转移枚举长度以及个数(枚举个数是nlogn的)

后来发现不用枚举长度,先假设放最短的然后枚举扩展的长度再放进去(brb可以往两边加r),最后直接组合数即可n^5log

然后100个点里挂了3个,原因是从大往小放的话放完一个段之后可能要去掉一些不选的,如果加一维就是n^6log

实际上直接从小往大放即可n^5log

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%1000000007
#define min(a,b) (a<b?a:b)
#define mod 1000000007
#define Mod 1000000005
#define ll long long
#define N 1000
//#define file
using namespace std;

ll f[71][71][72],jc[N+1],Jc[N+1],ans;
int d[71],n,m,i,j,k,l,x,y;
char a[71];
bool bz[71];

ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;};
ll C(int n,int m) {if (n<m) return 0;return jc[n]*Jc[m]%mod*Jc[n-m]%mod;}

int main()
{
	#ifdef file
	freopen("arc089F.in","r",stdin);
//	freopen("a.out","w",stdout);
	#endif
	
	jc[0]=1;
	fo(i,1,N) jc[i]=jc[i-1]*i%mod;
	Jc[N]=qpower(jc[N],Mod);
	fd(i,N-1,0) Jc[i]=Jc[i+1]*(i+1)%mod;
	
	scanf("%d%d",&n,&m);
	scanf("%s",a+1);
	ans=1;
	fo(x,0,n)
	{
		fo(y,0,n)
		if (x || y)
		{
			memset(bz,0,sizeof(bz)),k=l=0;
			fo(i,1,x)
			{
				fo(j,1,m) if (!bz[j] && a[j]=='r') break;
				fo(k,j,m) if (!bz[k] && a[k]=='b') break;
				if (k>m) break;
				bz[j]=bz[k]=1;
			}
			if (k>m) continue;
			fo(i,1,m) if (l<y && !bz[i] && a[i]=='r') ++l,bz[i]=1;
			if (l<y) continue;
			
			l=0;
			fd(j,m,1)
			if (bz[j] && a[j]=='b')
			{
				d[++l]=0;
				fo(k,j,m) d[l]+=!bz[k];
			}
			
			memset(f,0,sizeof(f)),f[0][0][0]=1;
			fo(i,0,x-1)
			{
				fo(j,0,d[x])
				{
					fo(k,0,d[x])
					if (f[i][j][k])
					{
						if (k<d[x]) add(f[i][j][k+1],f[i][j][k]);
						fo(l,1,x-i)
						if (j+l*k<=d[i+l])
						add(f[i+l][j+l*k][k+1],f[i][j][k]*C(i+l+y,l));
						else break;
					}
				}
			}
			
			fo(j,0,d[x])
			{
				fo(k,0,d[x]+1)
				{
					fo(l,0,n)
					add(ans,f[x][j][k]*C(l+(y+2*j+x*3)-1,(y+2*j+x*3)-1)%mod*C(n-(x+y-1)-2*j-l,x+y));
				}
			}
		}
	}
	printf("%lld\n",ans);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-09-30 12:45  gmh77  阅读(209)  评论(0编辑  收藏  举报