hdu2067和hdu1023 卡特兰数解法与大数处理

上次用DP将这首题给水过去了。因为这里N<=35.
现在我们来研究一下当N<100时的卡特数。通过资料我们可以发现,

n=100时,卡特兰数长度也就才58;
所以对于普通的题目,我们开a[110][110],足够的了。我们先打表后计算。不过要注意的是,最后的结果是卡特兰数的2倍。
这道题既然是高精度,那肯定就要使用高精度的算法啦。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
#define N 110
int a[N][110];
void catalan(int n )
{
    memset(a,0,sizeof(a));
    a[0][0]=1;
    a[1][0]=1;
    a[2][0]=2;
    int tmp;
    int k ;
    int count ;
    int ai;
    count = 1;
    for(int i =2 ;i<=n;i++)
    {
       tmp = 0 ;
       k = 0 ;
       for(int j = 0 ;j<count;j++)
       {
           tmp = (4*i-2)*a[i-1][j]+k;
           //注意这里不可(4*i-2)/(n+1)计算出来,因为这样很有可能会不精确,无法保证整除。
           a[i][j]=tmp%10;
           k=tmp/10;
       }
       while(k)
       {
           a[i][count++]=k%10;
           k=k/10;
       }
       k = 0 ;
       tmp = 0;
       for(int j = count -1;j>=0;j--)//除法处理
       {
           k =a[i][j]+tmp*10;//本位的被除数,要将来自高位的余数乘以10
           a[i][j]=k/(i+1);//本位的商
           tmp=k%(i+1);//送往低位的余数,
       }
    }
}
int main()
{
    int n ;
    catalan(36);
    int t =1;
    int used[N]={0};
    while(scanf("%d",&n)&&n!=-1)
    {
        int i ;
        printf("%d %d ",t++,n);
        if(used[n]==0)//保证不重复计算,因为重复计算会多次乘以2,那样将错误
        {
            used[n]=1;
            i =1001;
            while(a[i]==0) i--;
            int tmp = 0 ;
            int k   = 0 ;
            int count = i+1;
            for(int j = 0;j<count;j++)
            {
                tmp = a[n][j]*2+k;
                a[n][j]=tmp%10;
                k=tmp/10;
            }
            while(k)
            {
                a[n][count++]=k%10;
                k=k/10;
            }
        }
        i =110;
        while(a[n][i]==0) i--;//处理0
        while(i>=0) printf("%d",a[n][i--]);
        printf("\n");
    }
    return 0 ;
}

应用这段代码,把输入输出改一下,就可以直接用于第1023题。
高精度运算,关键就是要有一个tmp不进位处理的结果,和一个向高位或低位进1借1的k.

你可能感兴趣的:(dp,HDU,卡特兰数,大数处理)