记录编号 23220 评测结果 AAAAAAAAAA
题目名称 [SCOI 2008] 着色方案 最终得分 100
用户昵称 Gravatar.Xmz 是否通过 通过
代码语言 C++ 运行时间 0.162 s
提交时间 2011-03-03 10:00:41 内存使用 11.71 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>

using namespace std;

struct node
{
	long long f;
	int num[6],k;
	node *next;
	node()
	{
		f=-1;
		next=NULL;
	}
}hash[200001],lian[100001];
int lh;

int MOD(long long x)
{
	x%=1000000007;
	return x;
}

void add(node *&p,int *n,int k,long long f)
{
	if (!p)
	{
		p=&lian[++lh];
		for (int i=1;i<=5;i++) p->num[i]=n[i];
		p->k=k;
		p->f=MOD(f);
	}
	else
	{
		for (int i=1;i<=5;i++) if (p->num[i]!=n[i])
		{
			add(p->next,n,k,f);
			return ;
		}
		if (p->k!=k) {add(p->next,n,k,f);return ;}
		p->f = MOD((long long)p->f + f);
	}
}

void addd(node *p,int *n,int k,long long f)
{
	for (int i=1;i<=5;i++) if (p->num[i]!=n[i])
	{
		add(p->next,n,k,f);
		return ;
	}
	if (p->k!=k) {add(p->next,n,k,f);return ;}
	p->f = MOD((long long)p->f + f);
}

int has(int *n,int k)
{
	int hn=0;
	for (int i=1;i<=5;i++) hn=(17*hn+n[i]) % 199991;
	hn=(17*hn+k) % 199991;
	return hn;
}

void newnode(int *n,int k,long long f)
{
	int hn=has(n,k);
	
	if (hash[hn].f==-1)
	{
		for (int i=1;i<=5;i++) hash[hn].num[i]=n[i];
		hash[hn].k=k;
		hash[hn].f=MOD(f);
	}
	else addd(hash+hn,n,k,f);
}

node *find(node *p,int *n,int k)
{
	if (!p) return NULL;
	else
	{
		for (int i=1;i<=5;i++) if (p->num[i]!=n[i]) return find(p->next,n,k);
		if (p->k!=k) return find(p->next,n,k);
		return p;
	}
}

int c[16],K,num[6],t[6];
void dp()
{
	newnode(num,0,1);
	int n[6];
	for (int T=K;T>=0;T--)
	for (n[5]=min(T,num[5]);n[5]>=0;n[5]--)
	for (n[4]=min(T,num[4]+num[5]-n[5]);n[4]>=0;n[4]--)
	for (n[3]=min(T,num[3]+num[5]-n[5]+num[4]-n[4]);n[3]>=0;n[3]--)
	for (n[2]=min(T,num[2]+num[5]-n[5]+num[4]-n[4]+num[3]-n[3]);n[2]>=0;n[2]--)
	{
		n[1]=T-n[5]-n[4]-n[3]-n[2];
		if (n[1]<0) continue;
		for (int lastc=0;lastc<=5;lastc++)
		if (find(hash+has(n,lastc),n,lastc)!=NULL)
		for (int newc=1;newc<=5;newc++) if (n[newc]>0)
		{
			node *p=find(hash+has(n,lastc),n,lastc);
			if (newc!=lastc)
			{
				for (int i=1;i<=5;i++) t[i]=n[i];
				t[newc-1]++;t[newc]--;
				newnode(t,newc-1,p->f*n[newc]);
			}
			else
			{
				for (int i=1;i<=5;i++) t[i]=n[i];
				t[newc-1]++;t[newc]--;
				newnode(t,newc-1,p->f*(n[newc]<1 ? 0 : n[newc]-1));
			}
		}
	}
}

int main()
{
	freopen("color.in","r",stdin);
	freopen("color.out","w",stdout);
	scanf("%d",&K);
	for (int i=1;i<=K;i++) 
	{	
		scanf("%d",c+i);
		++num[c[i]];
	}
	dp();
	for (int i=1;i<=5;i++) num[i]=0;
	node *p=find(hash,num,0);
	cout<<((p->f < 0) ? 0 : p->f )<<"\n";
	return 0;
}