zoukankan      html  css  js  c++  java
  • [NOIP2003]栈 题解(卡特兰数)

    [NOIP2003]栈

    Description

    宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n。

    现在可以进行两种操作:
    1.将一个数,从操作数序列的头端移到栈的头端(对应数据结构栈的push操作)
    2.将一个数,从栈的头端移到输出序列的尾端(对应数据结构栈的pop操作)
    使用这两种操作,由一个操作数序列就可以得到一系列的输出序列;

    你的程序将对给定的n,计算并输出由操作数序列1,2,…,n经过操作可能得到的输出序列的总数。

    Solution

    1.题目可将进栈记为0,出栈记为1,那么问题即为求由n个0和n个1组成的字符串数,条件是每个1出现前必须有一个对应的0出现;

    2.那么可以推得方案数为总方案数减半,解与求01串的个数相同:n个0与n个1构成的序列方案数,使得任何一个前缀0的个数不少于1的个数;
    做法是将0看做在坐标系中向右走一步,1看做向上走一步,则问题可化简为从原点到(n,n)所有路线中一直处于y=x之下(不越过直线y=x)的不同路径方案数,方案数即为对应n的卡特兰数;

    3.因为没有要求取模,可以考虑使用高精度运算,输出n对应的卡特兰数即可;

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int ans[100001]={},x=0; 
    void mul(int n){
        for(int i=1;i<=ans[0];++i){
            ans[i]=ans[i]*n+x;
            x=ans[i]/10;
            ans[i]%=10;
        }
        while(x>0){
            ans[0]++;
            ans[ans[0]]=x%10;
            x/=10;
        }
    }
    void div(int n){
        int q=0;
        for(int i=ans[0];i>=1;--i)
         {
         	x=(ans[i]+q*10)%n;
         	ans[i]=(ans[i]+q*10)/n;
         	q=x;
         }
         while(ans[ans[0]]==0)ans[0]--;
    }
    int main(){
        ans[0]=ans[1]=1;
        int n;
        scanf("%d",&n);
        for(int i=n+2;i<=(n<<1);++i)mul(i);
        for(int i=2;i<=n;++i) div(i);
        for(int i=ans[0];i>0;--i)printf("%d",ans[i]);
        printf("
    ");
        return 0;
    }
    

    卡特兰数基础知识部分可以参考我的题解:http://www.cnblogs.com/COLIN-LIGHTNING/p/8450053.html

  • 相关阅读:
    Linux 只显示目录或者文件方法
    Linux awk命令用法
    Linux sed命令用法
    python环境通过selenium实现自动化web登陆及终端邀请
    python3 selenium实现自动登陆网页
    Mybatis(3)-基于代理Dao实现CRUD操作
    Mybatis(2)-自定义mybatis分析(理解其原理)
    Oracle数据库连接工具的使用(三)
    Mybatis(1)-初识mybaits
    Oracle数据库连接工具的使用(二)
  • 原文地址:https://www.cnblogs.com/COLIN-LIGHTNING/p/8481413.html
Copyright © 2011-2022 走看看