Andrew Stankevich—1
来源:互联网 发布:spss数据分析教程 编辑:程序博客网 时间:2024/06/07 06:42
Consider all regular bracket sequences with one type of brackets. Let us call the depth of the sequence the maximal difference between the number of opening and the number of closing brackets in a sequence prefix. For example, the depth of the sequence "()()(())" is 2, and the depth of "((()(())()))" is 4.
Find out the number of regular bracket sequences with n opening brackets that have the depth equal to k. For example, for n = 3 and k = 2 there are three such sequences: "()(())", "(()())", "(())()".
Input
Input file contains several test cases. Each test case is described with n and k (1 <= k <= n <= 50).
Last testcase is followed by two zeroes. They should not be processed.
Output
For each testcase output the number of regular bracket sequences with n opening brackets that have the depth equal to k.
Separate output for different testcases by a blank line. Adhere to the format of the sample output.
Sample Input
3 237 230 0
Sample Output
Case 1: 3Case 2: 203685956218528
Author: Andrew Stankevich
Source: Andrew Stankevich's Contest #7
【分析】
...不得不说这个系列的题目真的挺不错的..做起来挺复杂但是也挺有趣的
题意:给你n对括号,让你求出深度为k的方案数,深度就是说最深的嵌套括号层数.题目里有解释
显然这里要考虑的是dp,对于f[i][j]表示i对括号能组成深度不超过j的方案数,状态转移还是比较巧妙的,我们考虑一点,那就是
如果给你一个当前状态s,它的深度是a,那么它其中一定有一个会有一个 (s1) 存在,s1的深度是a-1,那么对于这个 (s1) 它的周围不管怎么加括号,都不会影响深度,只会增加方案数,当然它周围增加的括号深度不能比a-1大,
所以就发现了一个状态转移那就是f[k-1][j-1]*f[i-k][j],这里的k∈[1,i]然后把这些状态的方案数全部加起来就是f[i][j]
所以f[i][j]=sum( f[k-1][j-1]*f[i-k][j] ) (1<=k<=i)
那么状态转移方程已经有了,剩下的就是初始化了,一开始我想到的初始化是f[i][1]=1,显然对于深度为1的状态只可能是()()()()()这种类型
但是我计算之后发现,其实初始化应该是f[0][j],因为对于状j态转移,会出现f[0][j]这个位置,也就是k=i的时候,当然再做一次f[i][1]的初始化也是没有问题的~区别就是你做两层初始化和做一层初始化的区别。。本质上没有任何区别。。
那么剩下的问题就是高精度了,首先我们需要高精度乘法和加法,然后考虑到f[i][j]表示的是深度不超过j的方案数,但是我们需要的是深度为j的方案数,所以~答案应该是f[n][m]-f[n][m-1],也就是说还需要一个高精度减法....挺考验细节的....很有意思的题目
【代码】
#include <stdio.h>#include <string.h>int f[55][55][100];int a[100];int len;void add(int i,int j,int k){//[k-1][j-1]*[i-k][j]memset(a,0,sizeof(a));for (int ii=1;ii<=f[i-k][j][0];ii++)for (int jj=1;jj<=f[k-1][j-1][0];jj++)a[ii+jj-1]+=f[i-k][j][ii]*f[k-1][j-1][jj];for (len=1;a[len]||(len<f[i-k][j][0]+f[k-1][j-1][0]-1);len++) {a[len+1]+=a[len]/10;a[len]%=10;}len--;if (len<f[i][j][0]) len=f[i][j][0];for (int ii=1;ii<=len;ii++){f[i][j][ii]+=a[ii];f[i][j][ii+1]+=f[i][j][ii]/10;f[i][j][ii]%=10;}while(f[i][j][len+1]) f[i][j][len+1]+=f[i][j][len]/10,f[i][j][len]%=10,len=len+1;f[i][j][0]=len;}void init(){memset(f,0,sizeof(f));for (int i=0;i<=50;i++)f[0][i][1]=f[0][i][0]=1;for (int i=1;i<=50;i++)for (int j=1;j<=50;j++)for (int k=1;k<=i;k++)add(i,j,k);}void write(int n,int m){memset(a,0,sizeof(a));for (int i=1;i<=f[n][m][0];i++){a[i]+=f[n][m][i]-f[n][m-1][i];if (a[i]<0) a[i]+=10,a[i+1]--;}len=f[n][m][0];while (!a[len]) len--;for (int i=len;i>0;i--) printf("%d",a[i]);printf("\n");}int main(){init();int n,m;int pp=0;while (~scanf("%d%d",&n,&m) && (n||m)){if (pp) printf("\n");printf("Case %d: ",++pp);write(n,m);}return 0;}
- Andrew Stankevich—1
- Andrew Stankevich—2
- Andrew Stankevich's Contest (1)
- ZOJ 2313 Andrew Stankevich's Contest #1
- Andrew Stankevich's Contest #1 Solution
- 【ACdream】Andrew Stankevich Contest (1)
- ACdream Andrew Stankevich's Contest(1)
- ACdream Andrew Stankevich's Contest(1)
- Andrew Stankevich Contest
- Andrew Stankevich Contest 4——Driving Straight
- Andrew Stankevich's Contest (21)
- Andrew Stankevich Contest 46 [Solo]
- Andrew Stankevich's Contest 23
- Andrew Stankevich Contest 28 - F
- Andrew Stankevich Contest 28 - I
- 【ACdream】1403 Graph Game Andrew Stankevich Contest 21 二分匹配——关键点
- Andrew Stankevich's Contest #8 Solution
- Andrew Stankevich's Contest #2 Solution
- 【BootStrap】栅格系统、表单样式与按钮样式-附有源码
- 单例模式
- C++——数位DP模板——Windy数【四川省选2009】
- 常用Linux运维指令汇总
- 打开 DNS 拒绝访问
- Andrew Stankevich—1
- Android5.0之Toolbar详解
- 【Deep Learning】目录(初校)
- 方法的重写override
- 深入理解 Java 反射:Field (成员变量)
- js改变input的type属性
- 磁盘阵列的创建和管理
- MCM Problem C Overview
- 滑动拼图解锁