luogu P1044 火车进出栈问题(Catalan数)
Catalan数就是魔法
火车进出栈问题即:
一个栈(无穷大)的进栈序列为 1,2,3,4,...,n 求有多少个不同的出栈序列?
将问题进行抽象, 假设'+'代表进栈, 则有'-'代表出栈
那么如果进栈序列为123, 则:
+ + + - - - 将1, 2, 3压入栈后再将3, 2, 1弹出 得到出栈序列为321
同样, + - + - + - 得到出栈序列为123
上面所述的均为合法进出栈的序列 可发现规律: 序列中 + 的个数等于 - 的个数
但是如 + - - + + - 这样的序列, 在栈为空时仍进行弹出操作的, 为非法序列
进一步将 + - 序列抽象到平面直角坐标系中, + 代表向右走一格, -代表向上走一格, 可知y = x直线下方的序列均为合法序列, 如下图所示:

到这里, 火车进出栈问题就已经抽象为非降路径(只能向上走或向右走的路径)的问题

对于路径计数问题:
1)从(0,0)到(n,n)的非降路径等于n个x和n个y的排列数 即路径数为C(2n, n);
2)如果不是合法序列, 则会经过上图中的红线, 不合法序列一定会经过点(n -1, n), 从(0, 0)到(n -1, n)有C(2n, 2n-1)种不合法的路径;
3)综合1), 2) 并依据组合数性质化简
推导出公式:

我们可以得到出栈序列的总数为C(2n, n) / (n + 1).
下面以luogu P1044 栈为例, 完整代码如下:
/*
* @Author: Hellcat
* @Date: 2020-02-27 15:54:37
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll; ll C(int n, int m) {
ll ans = ;
for(ll i = ; i <= m; i++)
ans = ans * (n - m + i) / i;
return ans;
} int main() {
int n;
scanf("%d", &n);
printf("%lld\n", C(*n, n) / (n + ));
}
题给数据量不大 选择高效的组合数计算方法即可 无需高精度算法.
同时给出完全模拟的dfs暴力搜索算法如下:
dfs时候需要注意 为保证字典序输出优先考虑出栈.
#include <bits/stdc++.h>
using namespace std; int n, cnt = ;
vector<int> state1;
stack<int> state2;
int state3 = ; int res = ; void dfs() {
if(!cnt) return;
if(state1.size() == n) {
res++;
cnt--;
for(auto x : state1) cout<<x;
puts("");
return;
}
// 按字典序输出 则出栈先
if(state2.size()) { // 出栈
state1.push_back(state2.top());
state2.pop();
dfs();
state2.push(state1.back()); // 回溯
state1.pop_back();
}
if(state3 <= n) { // 入栈
state2.push(state3);
state3++;
dfs();
state3--; // 回溯
state2.pop();
}
} int main() {
scanf("%d", &n);
dfs();
printf("%d\n", res);
}
输入
3
输出
123
132
213
231
321
5
luogu P1044 火车进出栈问题(Catalan数)的更多相关文章
- 【讲●解】火车进出栈类问题 & 卡特兰数应用
火车进出栈类问题详讲 & 卡特兰数应用 引题:火车进出栈问题 [题目大意] 给定 \(1\)~\(N\) 这\(N\)个整数和一个大小无限的栈,每个数都要进栈并出栈一次.如果进栈的顺序为 \( ...
- tyvj/joyoi 1374 火车进出栈问题(水水版)
我受不了了. Catalan数第100项,30000项,50000项,cnm 这tm哪里是在考数学,分明是在考高精度,FFT...... 有剧毒! 我只得写高精度,只能过100的那个题,两个进化版超时 ...
- CH1102 火车进出栈问题(高精/卡特兰数)
描述 一列火车n节车厢,依次编号为1,2,3,-,n.每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种. 输入格式 一个数,n(n<=60000) 输出格式 一个数s表示 ...
- 洛谷P1044 栈(Catalan数)
P1044 栈 题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要 ...
- 火车进出栈 java
题目描述 一列火车n节车厢,依次编号为1,2,3,…,n.每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种. 输入 一个数,n(n<=60000) 输出 一个数s表示n节 ...
- Catalan数与出栈顺序个数,Java编程模拟
问题描述: 队列中有从1到7(由小到大排列)的7个整数,问经过一个整数栈后,出栈的所有排列数有多少?如果整数栈的容量是4(栈最多能容纳4个整数),那么出栈的排列数又是多少? 分析:对于每一个数字i, ...
- Catalan数 && 【NOIP2003】出栈序列统计
令h(1)=1, h(0)=1,catalan数满足递归式: h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)h(0) (n>=2) =C(2n, n)/(n+1) ...
- Catalan数,括号序列和栈
全是入门的一些东西.基本全是从别处抄的. 栈: 支持单端插入删除的线性容器. 也就是说,仅允许在其一端加入一个新元素或删除一个元素. 允许操作的一端也叫栈顶,不允许操作的一端也叫栈底. 数个箱子相叠就 ...
- [Catalan数]1086 栈、3112 二叉树计数、3134 Circle
1086 栈 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 栈是计算机中 ...
随机推荐
- selenium+python自动化用例登陆界面模板
一.基本逻辑 1.自动填写用户名和密码登录成功后跳转到相应页面 2.验证相应页面的url与给定的url是否一致,如果一致则测试通过,如果不一致则不通过 二.以jenkins登陆界面为例,代码如下 fr ...
- pwnable.kr-random-Writeup
MarkdownPad Document *:first-child { margin-top: 0 !important; } body>*:last-child { margin-botto ...
- Python - 装饰器实现缓存
from functools import wraps def cache(func): cache = {} @wraps(func) def wrap(*args): if args not in ...
- 91云服务器网络带宽测试,IO测试、全国ping测试
91yun服务器测试一键包介绍 一键包主要是为了让大家快速对服务器的基本状况有一个了解.考虑到天朝的网络出口问题,所以这个一键包更加偏向网络的测试. 影响测试耗时主要是下载,整个测试如果是能跑满100 ...
- 解决maven项目java中配置文件打包被忽略
pom.xml中添加以下配置 <build> <!--配置打包时不过滤非java文件开始 --> <!--说明,在进行模块化开发打jar包时,maven会将非java文件 ...
- java 实现一段文字中,出现次数最多的字
代码如下: public static void main(String[] args) { String str = "大批量,之前都没怎么注意过,这个问题确实不会,网上参考了下别人的,大 ...
- SpringCloud或SpringBoot+Mybatis-Plus利用mybatis插件实现数据操作记录及更新对比
引文 本文主要介绍如何使用mybatis插件实现拦截数据库操作并根据不同需求进行数据对比分析,主要适用于系统中需要对数据操作进行记录.在更新数据时准确记录更新字段 核心:mybatis插件(拦截器). ...
- python csv 读写操作
import csv def read_csvList(path="./datasets/test.csv")->list: """return ...
- ASP.NET Core搭建多层网站架构【7-使用NLog日志记录器】
2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...
- eclipse修改工作空间编码格式
一.修改workspace默认编码 eclipse打开window -> 打开preferences 二.修改jsp默认编码 eclipse打开window -> 打开preference ...