• bzoj 1079 着色方案


    Written with StackEdit.

    Description

    (n)个木块排成一行,从左到右依次编号为(1~n)。你有(k)种颜色的油漆,其中第(i)种颜色的油漆足够涂(c_i)个木块。
    所有油漆刚好足够涂满所有木块,即(c_1+c_2+...+c_k=n)。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。

    Input

    第一行为一个正整数(k),第二行包含(k)个整数(c_1, c_2, ... , c_k)

    Output

    输出一个整数,即方案总数模(10^9+7)的结果。

    Sample Input

    3
    1 2 3

    Sample Output

    10

    HINT

    (100\%)的数据满足:(1 <= k <= 15, 1 <= ci <= 5).

    Solution

    • 看上去很像状压?然而状压是压不下的...
    • 关键在于,两种油漆,如果可使用次数相同,那么它们其实是等价的.
    • 也就是说我们实际需要考虑的只有(5)种.
    • 直接开(5)维,用(f[a][b][c][d][e][pre])来表示各个次数的颜色剩余的种类以及上个颜色原来的次数确定时的方案数.
    • 转移时需要注意,若上个是种类(i),那么就会有一种颜色的次数减少了(1),导致(i-1)这一位传递进来时加了(1).但我们不能用它,在统计时要减去.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int P=1e9+7;
    inline int add(int a,int b)
    {
    	return (a + b) % P;
    }
    inline int mul(int a,int b)
    {
    	return 1LL * a * b % P;
    }
    int n=0,k;
    const int MAXK=16;
    int col[16],t[6];
    int f[MAXK][MAXK][MAXK][MAXK][MAXK][6];
    int dfs(int a,int b,int c,int d,int e,int pre)
    {
    	int &res=f[a][b][c][d][e][pre];
    	if(res!=-1)
    		return res;
    	res=0;
    	if(a+b+c+d+e==0)
    		return res=1;
    	if(a)
    		res=add(res,mul(a-(pre==2),dfs(a-1,b,c,d,e,1)));
    	if(b)
    		res=add(res,mul(b-(pre==3),dfs(a+1,b-1,c,d,e,2)));
    	if(c)
    		res=add(res,mul(c-(pre==4),dfs(a,b+1,c-1,d,e,3)));
    	if(d)
    		res=add(res,mul(d-(pre==5),dfs(a,b,c+1,d-1,e,4)));
    	if(e)
    		res=add(res,mul(e,dfs(a,b,c,d+1,e-1,5)));
    	return res;
    }
    int main()
    {
    	k=read();
    	for(int i=1;i<=k;++i)
    		{
    			col[i]=read();
    			n+=col[i];
    			++t[col[i]];
    		}
    	memset(f,-1,sizeof f);
    	int ans=dfs(t[1],t[2],t[3],t[4],t[5],0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    centos7使用supermin制作centos7的docker镜像包
    Linux ip netns 命令
    ip命令讲解
    openstack API应用用
    在EF6.0中打印数据库操作日志
    EF记录统一添加创建,修改时间
    Inner Join and Left Join 与条件的结合
    字符串分割
    居中方案
    移动 前端 框架
  • 原文地址:https://www.cnblogs.com/jklover/p/10072785.html
Copyright © 2020-2023  润新知