The Number of the Same BST_组合数优化_2018_2_21

16 篇文章 0 订阅
Many people knows binary search tree. The keys in a binary search tree are always stored in such a way as to satisfy the BST property:

Let x be a node in a binary search tree. If y is a node in the left subtree of x, then key[y] <= key[x]. If y is a node in the right subtree of x, then key[y] > key[x].

For example,

It is a binary search tree. And it can be built by inserting the elements of vector A <12, 6, 3, 18, 20, 10, 4, 17, 20> sequentially. But it can also be built by the vector B <12, 18, 17, 6, 20, 3, 10, 4, 20>.

Now given a vector X, then you may get a binary search tree from X. Your job is to calculate how many different vectors can build the same binary search tree. To make it easy, you should just output the number of different vectors mod 9901.
Input
Input consists of several cases. Each case starts with a line containing one positive integer n, which is the length of test vector. The integer n is less than 100. Following this there will be n positive integers, which are less then 10000, on the next line. The input will end with a case starting with n = 0. This case should not be processed.
Output
For each test case, print a line with a single integer, which is the number of different vectors mod 9901.
Sample Input
3
2 1 3
9
5 6 3 18 20 10 4 17 20
0
Sample Output
2
168

#include<iostream>
#include<cstring>
using namespace std;

const int mod=9901;
const int N=3e5+10;
int a[N],size[N],n,ans;

void insert(int x){
	int p=1;
	while(size[p]){
		size[p]++;
		if(x<=a[p])p*=2;
		else p=p*2+1;
	}
	a[p]=x;
	size[p]=1;
}

int cal(int x){
	int s=x,i;
	for(i=1;i<=mod;i++){
		if(s%mod==1)break;
		s+=x;
	}
	return i;
}

void dfs(int p){
	ans=ans*cal(size[p])%mod;
	if(size[p*2])dfs(p*2);
	if(size[p*2+1])dfs(p*2+1);
}

int main(){
	while(scanf("%d",&n),n){
		memset(a,0,sizeof(a));
		memset(size,0,sizeof(size));
		int i,x;
		for(int i=1;i<=n;i++){
			scanf("%d",&x);
			if(i==1)a[i]=x,size[i]=1;
			else insert(x);
		}
		ans=1;
		dfs(1);
		for(int i=2;i<=n;i++)
		ans=ans*i%mod;
		printf("%d\n",ans);
	}
}











 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值