POJ 1671 Rhyme Schemes

来源:互联网 发布:winscp中文版mac 编辑:程序博客网 时间:2024/06/03 20:25
Rhyme Schemes
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 1175 Accepted: 645 Special Judge

Description

The rhyme scheme for a poem (or stanza of a longer poem) tells which lines of the poem rhyme with which other lines. For example, a limerick such as If computers that you build are quantum 
Then spies of all factions will want 'em 
Our codes will all fail 
And they'll read our email 
`Til we've crypto that's quantum and daunt 'em 

Jennifer and Peter Shor (http://www.research.att.com/~shor/notapoet.html) 

Has a rhyme scheme of aabba, indicating that the first, second and fifth lines rhyme and the third and fourth lines rhyme. 
For a poem or stanza of four lines, there are 15 possible rhyme schemes: 
aaaa, aaab, aaba, aabb, aabc, abaa, abab, abac, abba, abbb, abbc, abca, a bcb, abcc, and abcd. 
Write a program to compute the number of rhyme schemes for a poem or stanza of N lines where N is an input value.

Input

Input will consist of a sequence of integers N, one per line, ending with a 0 (zero) to indicate the end of the data. N is the number of lines in a poem.

Output

For each input integer N, your program should output the value of N, followed by a space, followed by the number of rhyme schemes for a poem with N lines as a decimal integer with at least 12 correct significant digits (use double precision floating point for your computations).

Sample Input

12342030100

Sample Output

1 12 23 54 1520 5172415823537230 84674901451180912000000010 115975

Source

Greater New York 2003

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <algorithm>using namespace std;#define MAXN 100double f[MAXN][MAXN];double dfs(int high, int len){int i;double ret;if (len == 1) return high;if (f[len][high] >= 0) return f[len][high];for (i = 1, ret = 0; i <= high; i++){ret += dfs(max(high, i + 1), len - 1); }return f[len][high] = ret;}int main(){int i, j, n;for (i = 0; i < MAXN; i++)for (j = 0; j < MAXN; j++)f[i][j] = -1;while(scanf("%d", &n), n != 0){printf("%d %.0f\n", n, dfs(1, n));}return 0;}/*问题:将n个点分成一个个集合,问分法数。例如,n=4,aaab, aaba, abcd, 是不同分法,但是aaab = bbba, abcd = abdc从输入样例可以看出, abdc这种写法是不合法的,或者说是没必要考虑类似数位DP做的数学上,叫第二类Stirling数S(n,k) = k*S(n-1,k) + S(n-1,k-1)状态: 前n个点,分成了k个集合奇怪的,n=50以后,结果为0,再大点就RE了...*/

补充:

Bell数
又称为贝尔数,是以埃里克·坦普尔·贝尔(Eric Temple Bell)为名的。
B(n)是包含n个元素的集合的划分方法的数目。B(0) = 1, B(1) = 1, B(2) = 2, B(3) = 5, B(4) = 15, B(5) = 52, B(6) = 203,...递推公式为,B(0) = 1,B(n+1) = Sum(0,n) C(n,k)B(k). n = 1,2,...其中,Sum(0,n)表示对k从0到n求和,C(n,k) = n!/[k!(n-k)!]-------------------------Stirling数
又称为斯特灵数,在组合数学,Stirling数可指两类数,都是由18世纪数学家James Stirling提出的。第一类Stirling数是有正负的,其绝对值是包含n个元素的集合分作k个环排列的方法数目。递推公式为,S(n,0) = 0, S(1,1) = 1.S(n+1,k) = S(n,k-1) + nS(n,k)。第二类Stirling数是把包含n个元素的集合划分为正好k个非空子集的方法的数目。递推公式为,S(n,n) = S(n,1) = 1,S(n,k) = S(n-1,k-1) + kS(n-1,k).-------------每个贝尔数都是"第二类Stirling数"的和。B(n) = Sum(1,n) S(n,k).