uva 10157 expressions

Problem A: EXPRESSIONS 



Let X be the set of correctly built parenthesis expressions. The elements of X are strings consisting only of the characters �(� and �)�. The set X is defined as follows:

  • an empty string belongs to X
  • if A belongs to X, then (A) belongs to X
  • if both A and B belong to X, then the concatenation AB belongs to X.
For example, the following strings are correctly built parenthesis expressions (and therefore belong to the set X):

()(())()

(()(()))

The expressions below are not correctly built parenthesis expressions (and are thus not in X):

(()))(()

())(()

Let E be a correctly built parenthesis expression (therefore E is a string belonging to X).

The length of E is the number of single parenthesis (characters) in E.

The depth D(E) of E is defined as follows:

               ì 0 if E is empty 
D(E)= í D(A)+1 if E = (A), and A is in X 
               î max(D(A),D(B)) if E = AB, and A, B are in X

For example, the length of �()(())()� is 8, and its depth is 2.

What is the number of correctly built parenthesis expressions of length n and depth d, for given positive integers n and d?

Task 
Write a program which

  • reads two integers n and d
  • computes the number of correctly built parenthesis expressions of length n and depth d;
Input data  
Input consists of lines of pairs of two integers - n and d, at most one pair on line,  £ n £ 300, 1£ d £ 150. 
The number of lines in the input file is at most 20, the input may contain empty lines, which you don't need to consider.

Output data 
For every pair of integers in the input write single integer on one line - the number of correctly built parenthesis expressions of length n and depth d.

Example 
Input data                                   Output data 
6 2                 3 
300 150             1 

There are exactly three correctly built parenthesis expressions of length 6 and depth 2: 
(())() 
()(()) 
(()()) 



#include <cstdio>
#include <cstring>
#include <cassert>

const int LEN = 100;
const int NMAX = 300;
const int DMAX = 150;

int f[NMAX + 1][DMAX + 1][LEN];
bool isCalculated[NMAX + 1][DMAX + 1];

void add (int a[], int b[])
{
    int carry = 0;
    for (int i=0; i<LEN; ++i) {
        int n = (carry + a[i] + b[i]) % 10;
        carry = (carry + a[i] + b[i]) / 10;
        a[i] = n;
    }
    assert (carry == 0);
}

void substract (int a[], int b[])
{
    int borrow = 0;
    for (int i=0; i<LEN; ++i) {
        int n = (a[i] - b[i] + borrow + 10) % 10;
        borrow = (a[i] - b[i] + borrow + 10) / 10 - 1;
        a[i] = n;
    }
    assert (borrow == 0);
}

void multiply (int a[], int b[])
{
    static int c[LEN];
    memset (c, 0, sizeof (c));

    int I = LEN;
    while (--I >= 0 && a[I] == 0) {}
    ++I;

    int K = LEN;
    while (--K >= 0 && b[K] == 0) {}
    ++K;

    for (int i=0; i<I; ++i) {
        for (int k=0; k<K && i+k<LEN; ++k) {
            c[i + k] += a[i] * b[k];
        }
    }
    int carry = 0;
    for (int i=0; i<LEN; ++i) {
        int n = (carry + c[i]) % 10;
        carry = (carry + c[i]) / 10;
        c[i] = n;
    }
    assert (carry == 0);
    memcpy (a, c, sizeof (c));
}

void print (int a[])
{
    int i = LEN;
    while (--i > 0 && a[i] == 0) {}
    while (i >= 0) {
        printf ("%d", a[i--]);
    }
    printf ("\n");
}

void calculate (int n, int d)
{
#ifndef ONLINE_JUDGE
    printf ("calculate (%d, %d)\n", n, d);
#endif
    if (isCalculated[n][d]) {
        return;
    }

    isCalculated[n][d] = true;

    for (int i=0; i<LEN; ++i) {
        f[n][d][i] = 0;
    }

    if (n % 2 == 1) {
        return;
    }

    if (n == 0) {
        f[n][d][0] = 1;
        return;
    }

    if (d == 0) {
        return;
    }

    static int t[LEN];
    for (int i=0; i<n; i+=2) {

        assert (n - 2 - i >= 0);
        assert (d - 1 >= 0);

        calculate (i, d);
        calculate (n - 2 - i, d - 1);

        memcpy (t, f[i][d], sizeof (t));
        multiply (t, f[n - 2 - i][d - 1]);

        add (f[n][d], t);
    }

#ifndef ONLINE_JUDGE
    printf ("f[%d][%d] = ", n, d);
    print (f[n][d]);
#endif
}

int main (int argc, char *argv[])
{
    int n, d;
    while (scanf ("%d%d", &n, &d) == 2) {

        if (d == 0 && n == 0) {
            printf ("1\n");
            continue;
        } else if (d == 0) {
            printf ("0\n");
            continue;
        }

        calculate (n, d);
        calculate (n, d - 1);

        static int ans[LEN];
        memcpy (ans, f[n][d], sizeof (ans));
        substract (ans, f[n][d - 1]);

        print (ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值