UVaLive 4847 - Binary Search Tree (与BST有关的计数问题)

该博客讨论了如何计算给定一个1到N的排列A后,有多少不同的1到N排列会生成相同的二叉搜索树形态。通过分析每个节点的子节点数量,可以使用组合数学公式确定排列的总数,并对结果取模999991输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVALive - 4847

Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

[]   [Go Back]   [Status]  

Description

Download as PDF
A binary search tree is a binary tree. It may be empty. If it is not empty, it satisfies the following properties:

(1)
Every node has a key, and no two nodes have the same key.
(2)
The keys in a nonempty left subtree must be smaller than the key in the root of the subtree.
(3)
The keys in a nonempty right subtree must be larger than the key in the root of the subtree.
(4)
The left and right subtrees are also binary search trees.

Sample binary search trees are shown in Figure 1.

\epsfbox{p4847.eps}

Figure 1. binary search trees

To search for a node with a key k in a binary search tree T, we begin at the root. If T is empty, T contains no keys and the search is unsuccessful. Otherwise, we compare k with the key in root. If k equals root's key, then the search terminates successfully. If k is less than root's key, we search the left subtree of the root. If k is larger than root's key, we search the right subtree of the root. In the same way, we can proceed the search in the left or right subree of T.

To insert a new key k into a binary search tree T where k is different from those of existing keys in T, we first search the tree T. The search will be unsuccessful, then we insert the key at the point the search terminated. For instance, to insert a key 80 into the Figure 1(a), we first search the tree for 80. This search terminates unsuccessfully, and the last node examined has key 40. We insert a new node containing 80 as the right child of the node. The resulting search tree is shown in Figure 1(b).

In this problem, we consider binary search trees with N keys 1, 2,..., N. For a permutation a1 a2 ... aN of {1, 2,..., N}, inserting a1 a2 ... aNsuccessively into an initially empty binary search tree will produce a binary search tree. For instance, the permutation 2 1 4 3 5 will produce the tree in Figure 1(c). Also, 2 4 3 1 5 will produce the same tree. Actually, 8 permutations among all possible permutations of 1, 2, 3, 4, 5 will produce the same tree to the tree in Figure 1(c).

We are interested in finding the number of permutations of {1, 2,..., N} such that all those permutations produce a binary search tree identical to the tree produced by a given permutation P. Given N and P, you are to write a program that calculates the number of permutations satisfying the above condition.

Input

Your program is to read from standard input. The input consists of T test cases. The number of test cases T is given in the first line. Each test case starts with a line containing an integer N representing the number of keys, 1$ \le$N$ \le$20. In the next line, a permutation of length N is given. There is a single space between the integers representing keys in the permutation.

Output

Your program is to write to standard output. Print exactly one line for each test case as follows: Let B be the number of permutations that produce the binary search tree identical to the tree produced by the input permutation. Print B mod 9, 999, 991 for each test case. For example, if B = 20, 000, 000, the output should be 18 for that test case.

The following shows sample input and output for three test cases.

Sample Input

3
5
2 1 4 3 5
4
2 4 1 3
12
1 2 3 4 5 6 7 8 9 10 11 12

Sample Output

8
3
1

Source

[]   [Go Back]   [Status]  





题意:

给定一个1-n的排列A,依次插入一颗初始为空的排序二叉树中,问有多少1-n的排序和这个排列的最后形态相同。


比较容易想到的 对于一棵排序二叉树,他的种数=C(son[i], son[left[i]]),son[i]表示i的孩子数,left[i]表示i的左孩子标号。

从前到后扫描一遍,维护每个点的父亲,然后看后面有多少个点是他左孩子和右孩子,然后组合公式计算一下就行了





#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

//using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));

const int MOD = 9999991;
int A[30];
int left[30], right[30];
int fa[30], fad[30];
int C[30][30];

void init(int n) {
    memset(C, 0, sizeof(C));
    C[0][0] = 1;
    for(int i=1; i<n; i++) {
        C[i][0] = C[i][i] = 1;
        for(int j=1; j<i; j++) {
            C[i][j] = ( C[i-1][j-1] + C[i-1][j] ) % MOD;
        }
    }
}

int n;

int main() {
    int T;

    init(30);
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i=0; i<n; i++) {
            scanf("%d", &A[i]);
        }
        memset(fa, -1, sizeof(fa));
        memset(fad, 0, sizeof(fad));
        for(int i=0; i<n; i++) {
            left[i] = right[i] = 0;
            for(int j=i+1; j<n; j++) if(fa[j] == fa[i] && fad[i] == fad[j]) {
                fa[j] = i;
                if(A[j] < A[i]) left[i]++, fad[j] = 0;
                else right[i]++, fad[j] = 1;
            }
        }
        int ans = 1;
        for(int i=0; i<n-1; i++) {
            int all = left[i] + right[i];
            ans = ( ans * C[all][left[i]] ) % MOD;
        }
        printf("%d\n", ans);
    }

    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值