zoukankan      html  css  js  c++  java
  • arc089F

    题目大意


    题解

    半想半看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
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    删除排序链表中的重复元素
    动态规划之爬楼梯问题
    外行小白的modbus惊心之旅
    SSM框架整合
    我与404的不解之缘系列(一)记录一个智障一般的错误
    day 06 作业
    day 06 文件查看查找与上传下载
    linux 防火墙查看firewall
    linux 变量详情
    day05作业练习题
  • 原文地址:https://www.cnblogs.com/gmh77/p/13753970.html
Copyright © 2011-2022 走看看