Skip to content

11291: 【原1291】heaps

题目

题目描述

author: 王立力 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1291

Description

简单的描述往往意味着简单的题目。给定n个两两不同的数,用它们可以组成多少个不同的大小为n的堆?

提示:大根堆和小根堆都要考虑哦。

因为结果非常大,所以最后输出答案mod 1000000007的值即可。

Input Format

一个整数n

30%的数据n<=10

100%的数据n<=1000

Output Format

一行输出答案

Sample Input

3

Sample Output

4

zqy2018's solution

/*
    Hint: use combinatorics
*/
#include <bits/stdc++.h>
#define INF 2000000000
#define M 1000000007
using namespace std;
typedef long long ll;
int read(){
    int f = 1, x = 0;
    char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
    while(c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
    return f * x; 
}
int n, f[1005] = {0}, C[1005][1005] = {0};
void init(){
    n = read();
    C[0][0] = 1;
    for (int i = 1; i <= n; ++i){
        C[i][0] = 1;
        for (int j = 1; j <= i; ++j)
            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % M;
    }
}
void solve(){
    if (n <= 1) {
        printf("%d\n", n);
        return ;
    }
    f[1] = f[2] = 1;
    for (int i = 3; i <= n; ++i){
        int tt = 2;
        while (tt - 1 <= i)
            tt <<= 1;
        tt >>= 1;
        int lsize = min(tt >> 1, i - tt + 1);
        lsize += (tt - 1) >> 1;
        f[i] = 1ll * (C[i - 1][lsize]) * f[lsize] % M,
        f[i] = 1ll * f[i] * f[i - lsize - 1] % M;
    }
    int ans = 2ll * f[n] % M;
    printf("%d\n", ans);
}
int main(){
    init();
    solve();
    return 0;
}