[NDK 出栈序列统计]

[题目来源]:NOIP基础题目集

[关键字]:数学

[题目大意]:求出n个数的出栈序列数目

//===========================================================================================================

[分析]:n个数的出栈序列数目就是一颗有n个节点的二叉树的数量。因为他的进栈序列就是该二叉树的先序遍历,而它的出栈序列就是该二叉树的中序遍历,所以两者都等于Catalan数公式为:C(2n,n)/(n+1)。因为当n稍微大一点时结果就会很大,所以要用高精度,为了避免高精除法,可以先将把分子和分母分别写成几个质数相乘的形式,再约分(指数相减)。

[代码]:

View Code
  1 program Project1;
2 type
3 rec = record
4 len: longint;
5 dat: array[0..2000] of longint;
6 end;
7 var
8 ans: rec;
9 d: array[0..200] of longint;
10 su: array[0..200] of longint;
11 n, tot: longint;
12
13 procedure cheng(var ans: rec; x: longint);
14 var
15 i, k: longint;
16 begin
17 k := 0;
18 for i := 1 to ans.len do
19 begin
20 ans.dat[i] := ans.dat[i]*x+k;
21 k := ans.dat[i] div 10;
22 ans.dat[i] := ans.dat[i] mod 10;
23 end;
24 while k > 0 do
25 begin
26 inc(ans.len);
27 ans.dat[ans.len] := k mod 10;
28 k := k div 10;
29 end;
30 end;
31
32 procedure work;
33 var
34 i, j, k: longint;
35 begin
36 for i := n+2 to 2*n do
37 begin
38 j := 0;
39 k := i;
40 while k > 1 do
41 begin
42 inc(j);
43 while k mod su[j] = 0 do
44 begin
45 inc(d[j]);
46 k := k div su[j];
47 end;
48 end;
49 end;
50 for i := 2 to n do
51 begin
52 j := 0;
53 k := i;
54 while k > 1 do
55 begin
56 inc(j);
57 while k mod su[j] = 0 do
58 begin
59 dec(d[j]);
60 k := k div su[j];
61 end;
62 end;
63 end;
64 ans.len := 1;
65 ans.dat[1] := 1;
66 for i := 1 to tot do
67 while d[i] > 0 do
68 begin
69 cheng(ans,su[i]);
70 dec(d[i]);
71 end;
72 for i := ans.len downto 1 do
73 write(ans.dat[i]);
74 end;
75
76 procedure make;
77 var
78 i, j: longint;
79 f: boolean;
80 begin
81 for i := 2 to 2*n do
82 begin
83 f := true;
84 for j := 2 to i-1 do
85 if i mod j = 0 then
86 begin f := false; break; end;
87 if f then
88 begin inc(tot); su[tot] := i; end;
89 end;
90 end;
91
92 begin
93 assign(input,'d:\in.txt');reset(input);
94 assign(output,'d:\out.txt');rewrite(output);
95 read(n);
96 make;
97 work;
98 close(input);
99 close(output);
100 end.

 

你可能感兴趣的:(NDK)