1187:陨石的秘密

描述

公元11380年,一颗巨大的陨石坠落在南极。于是,灾难降临了,地球上出现了一系列反常的现象。当人们焦急万分的时候,一支中国科学家组成的南极考察队赶到了出事地点。经过一番侦察,科学家们发现陨石上刻有若干行密文,每一行都包含5个整数:
1 1 1 1 6
0 0 6 3 57
8 0 11 3 2845
著名的科学家SS发现,这些密文实际上是一种复杂运算的结果。为了便于大家理解这种运算,他定义了一种SS表达式:
1. SS表达式是仅由'{','}','[',']','(',')'组成的字符串。
2. 一个空串是SS表达式。
3. 如果A是SS表达式,且A中不含字符'{','}','[',']',则(A)是SS表达式。
4. 如果A是SS表达式,且A中不含字符'{','}',则[A]是SS表达式。
5. 如果A是SS表达式,则{A}是SS表达式。
6. 如果A和B都是SS表达式,则AB也是SS表达式。


例如
()(())[]
{()[()]}
{{[[(())]]}}
都是SS表达式。

()([])()
[()
不是SS表达式。

一个SS表达式E的深度D(E)定义如下:

例如(){()}[]的深度为2。

密文中的复杂运算是这样进行的:
设密文中每行前4个数依次为L1,L2,L3,D,求出所有深度为D,含有L1对{},L2对[],L3对()的SS串的个数,并用这个数对当前的年份11380求余数,这个余数就是密文中每行的第5个数,我们称之为?神秘数?。
密文中某些行的第五个数已经模糊不清,而这些数字正是揭开陨石秘密的钥匙。现在科学家们聘请你来计算这个神秘数。
输入
共一行,4个整数L1,L2,L3,D。相邻两个数之间用一个空格分隔。
(0 <= L1 <= 10,0 <= L2 <= 10,0 <= L3 <= 10,0 <= D <= 30)
输出
共一行,包含一个整数,即神秘数。
样例输入
1 1 1 2
样例输出
8
来源
Noi 01


分析

用d[i][j][u][v]表示i个{},j个[],u个(),深度为v的序列数,根据最后一个子括号(就是最后一个反括号对应的正括号范围内的括号)分类计数。

最后一个子括号可能深度小于v,此时前面的括号深度必须为v,最后一个子括号深度也可能等于v,此时前面的括号深度可以小于或等于v。

用sum[i][j][u][v]表示i个{},j个[],u个(),深度小于等于v的序列数。没递推完i,j,u后,立即计算相应的sum[i][j][u][0…D]的值。

枚举最后一个子括号内有哪些括号完成递推。


代码
#include<stdio.h>
#include<stdlib.h>
int d[12][12][12][32];
int sum[12][12][12][32];
int main(void)
{
	int i,j,u,v,p,q,n,m,vi,vj,vu,sump;
	scanf("%d%d%d%d",&q,&n,&m,&p);
	d[0][0][0][0]=1;
	sum[0][0][0][0]=1;
	for(i=0;i<=q;i++)
	{
		for(j=0;j<=n;j++)
		{
			for(u=0;u<=m;u++)
			{
				for(v=1;v<=p;v++)
				{
					if(i+j+u<v)
					{
						d[i][j][u][v]=0;
					}
					else
					{
						if(i!=0)
						{
							sump=d[i-1][j][u][v-1];
						}
						else if(j!=0)
						{
							sump=d[0][j-1][u][v-1];
						}
						else if(u!=0)
						{
							sump=d[0][0][u-1][v-1];
						}
						else
						{
							sump=0;
						}
						for(vi=0;vi<=i;vi++)
						{
							for(vj=0;vj<=j;vj++)
							{
								for(vu=0;vu<=u;vu++)
								{
									if((vi+vj+vu!=0)&&(vi+vj+vu!=i+j+u))
									{
										if(vi!=0)
										{
											if(v>=2)
											{
												sump=(sump+sum[vi-1][vj][vu][v-2]*d[i-vi][j-vj][u-vu][v])%11380;
											}
											sump=(sump+d[vi-1][vj][vu][v-1]*sum[i-vi][j-vj][u-vu][v])%11380;
										}
										else if(vj!=0)
										{
											if(v>=2)
											{
												sump=(sump+sum[0][vj-1][vu][v-2]*d[i][j-vj][u-vu][v])%11380;
											}
											sump=(sump+d[0][vj-1][vu][v-1]*sum[i][j-vj][u-vu][v])%11380;
										}
										else
										{
											if(v>=2)
											{
												sump=(sump+sum[0][0][vu-1][v-2]*d[i][j][u-vu][v])%11380;
											}
											sump=(sump+d[0][0][vu-1][v-1]*sum[i][j][u-vu][v])%11380;
										}
									}
								}
							}
						}
						d[i][j][u][v]=sump;
					}
				}
				for(v=1;v<=p;v++)
				{
					sum[i][j][u][v]=(sum[i][j][u][v-1]+d[i][j][u][v])%11380;
				}
			}
		}
	}
	printf("%d\n",d[q][n][m][p]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值