【BZOJ2944】[Poi2000]代码(卡特兰数)
这题在网上找不到题解,硬写一下午终于写出来了……
题目:
BZOJ2944
分析:
首先明确:
比较两棵节点数相同的二叉树时,根节点是第一关键字,左子树是第二关键字,右子树是第三关键字;
然后我们分析一下题目中那个4个节点,14种代码的例子
左子树大小\(sl\) | 右子树大小\(sr\) | 根节点 | 对应名次 | 对应代码数量 | \(C_{sl}*C_{sr}\) |
---|---|---|---|---|---|
0 | 3 | a | 1~5 | 5 (abcd 、abdc、 acbd、 adbc、 adcb) | \(1*5=5\) |
1 | 2 | b | 6~7 | 2 (bacd、 badc) | \(1*2=2\) |
2 | 1 | c | 8~9 | 2 (cabd、 cbad) | \(2*1=2\) |
3 | 0 | d | 10~14 | 5 (dabc、 dacb、 dbac、 dcab、 dcba) | \(5*1=5\) |
(由于博客园的Markdown似乎不支持表格,此图截自我的CSDN博客)
(先不管最后一列)我们发现左子树大小决定了根节点的字母,并将这14种二叉树形态分成了长度为5、2、2、5的四“段”。因此,我们知道要求第多少名,就可以根据它在哪一段求出左子树的大小(比如样例中的第11名在第4段,因此左子树大小为3,代码一定以'd'开头)。并且这个过程可以递归下去,求出树的形态。代码如下
void dfs(ll n, int k, int tmp)
{
int sizel = 0, sizer = k - 1;
/*算出左子树的大小*/
printf("%c", (char)(sizel + tmp + 'a'));
if (sizel > 0)
dfs(/*左子树的名次*/, sizel, tmp);
if (sizer > 0)
dfs(/*右子树的名次*/, sizer, tmp + sizel + 1);
}
有一个结论,如果用\(C_n\)表示\(Catalan\)数的第n项,则\(n\)个结点的二叉树有\(C_n\)种不同的形态
(证明见Catalan number - Wikipedia,相关公式推导见【知识总结】卡特兰数 (Catalan Number) 公式的推导)
那么当根节点的字母固定,左右子树大小随之固定,以该字母开头的代码的数量就是\(C_{sl}*C_{sr}\),也就是上表最后一列。
根据这个性质,可以暴力算出根节点的字母和左右子树的大小,代码如下
while (n)
{
if (n > Catalan[sizel] * Catalan[sizer])
{
n -= Catalan[sizel] * Catalan[sizer];
sizel++, sizer--;
}
else
break;
}
这段代码执行后,\(n\)就是当根节点固定时该代码的排序(比如样例中dacb是以'd'开头的第二个,此时\(n=2\))
此时的排序是以左子树为第一关键字,右子树为第二关键字的。可以想象成一个两位数,个位满\(C_{sr}\)向十位进一。所以此时所求左子树在\(C_{sl}\)个左子树中的排名是\(\lceil \frac{n}{C_{sr}}\rceil\),所求右子树在\(C_{sr}\)个右子树中的排名是\(n\ mod\ C_{sr}\)(注意特判\(0\)的情况)
代码:
注意不是每一棵子树所代表的字母集合都是从'a'开始的,所以要有\(tmp\)变量
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
namespace zyt
{
typedef long long ll;
ll Catalan[20];
void dfs(ll n, int k, int tmp)
{
int sizel = 0, sizer = k - 1;
while (n)
{
if (n > Catalan[sizel] * Catalan[sizer])
{
n -= Catalan[sizel] * Catalan[sizer];
sizel++, sizer--;
}
else
break;
}
printf("%c", (char)(sizel + tmp + 'a'));
if (sizel > 0)
dfs(ceil((double)n / Catalan[sizer]), sizel, tmp);
if (sizer > 0)
{
int x = n % Catalan[sizer];
dfs(x ? x : Catalan[sizer], sizer, tmp + sizel + 1);
}
}
void work()
{
ll n;
int k;
scanf("%lld%d", &n, &k);
Catalan[0] = 1;
for (int i = 1; i <= k; i++)
Catalan[i] = Catalan[i - 1] * (4 * i - 2) / (i + 1);
dfs(n, k, 0);
}
}
int main()
{
zyt::work();
return 0;
}
【BZOJ2944】[Poi2000]代码(卡特兰数)的更多相关文章
- BZOJ2944 : [Poi2000]代码
对于根,要让它的排名尽量小,也就是要让右子树的点数尽量多. 于是从大到小枚举右子树的点数,用Catalan数计算方案数,直到找到相应的右子树的点数为止. 此时根的排名已经确定,接下来要让左子树的代码的 ...
- 卡特兰数(Catalan)
卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列.由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名,其前几项为 : 1, 2, ...
- HDU 5673 Robot ——(卡特兰数)
先推荐一个关于卡特兰数的博客:http://blog.csdn.net/hackbuteer1/article/details/7450250. 卡特兰数一个应用就是,卡特兰数的第n项表示,现在进栈和 ...
- HDU 1023 Traning Problem (2) 高精度卡特兰数
Train Problem II Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Sub ...
- hdu 1023 卡特兰数+高精度
Train Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HDU 1023 Train Problem II (卡特兰数,经典)
题意: 给出一个数字n,假设火车从1~n的顺序分别进站,求有多少种出站序列. 思路: 卡特兰数的经典例子.n<101,用递推式解决.需要使用到大数.n=100时大概有200位以下. #inclu ...
- 2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)
题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展g ...
- poj 1095 Trees Made to Order 卡特兰数
这题用到了卡特兰数,详情见:http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html 解体思路详见:http://blog.csdn. ...
- 【HDU 5370】 Tree Maker(卡特兰数+dp)
Tree Maker Problem Description Tree Lover loves trees crazily. One day he invents an interesting gam ...
随机推荐
- BZOJ 4094 USACO 2013 Dec. Optimal Milking
线段树 每个节点保存4个值,both表示左右端点都取,neither表示左右端点都不取,left表示只取左端点,right表示只取右端点. 维护的特殊姿势: $cur$的$both=max(ls.l+ ...
- Navicat premium连接Oracle报ORA-12541错误
1:ORA-12541 原因:Oracle TNS监听服务没开 解决:
- 抽象类和接口有什么区别---https://blog.csdn.net/csdn_aiyang/article/details/71171886
https://blog.csdn.net/csdn_aiyang/article/details/71171886 概念] 抽象类.具体类是相对的,并非绝对的.抽象是一种概念性名词,具体是一种可 ...
- HDU 1253 三维数组的图上找最短路
题目大意: 从三维空间的(0,0,0)出发到(a-1,b-1,c-1),每移动一个都要时间加一,计算最短时间 根据六个方向,开个bfs,像spfa那样计算最短路径就行了,但是要1200多ms,也不知道 ...
- tmux使用入门
tmux是Linux中窗口管理程序,适用于终端复用,尤其适合远程连接.最近,我正苦闷与ssh自动超时退出和broken pipe,决定投入tmux怀抱. 使用tmux最直接的好处,便是可以在一个远程连 ...
- java连接数据库(经常用)
一.配置环境 1.首先下载sqlserver2008驱动文件,找到sqljdbc4.jar文件,将这个文件拷到C:\Program Files\Java\jdk1.8.0_121\jre\lib\ex ...
- IT领域的罗马帝国——微软公司
微软公司从做软件开始,起步很小.但是盖茨确是一直深耕于战略布局,像一个棋局高手,每一步棋都是看了后面几步. 盖茨居然用9年的时间憋出一个win3.0,成功击败了apple. 而这9年拖住apple的居 ...
- Codeforces 303A(构造)
题意:对0到(n-1)这n个数进行全排列.请找出三个全排列a.b.c,使得“a与b的对应元素的和”与“c的对应元素”对模n同余,无解输出-1.(n<=1e5) 分析:n为奇数有解,n为偶数无解 ...
- Windows下React Native开发01 -- Android开发环境搭建
1.安装jdk 推荐将JDK的bin目录加入系统PATH环境变量(自己百度下怎么配置). 2.安装SDK 直接安装 Android Studio 推荐从AndroidDevTools下载.(也可以直 ...
- Redis: Useful commands
SELECT X - Select database (the X must be int) CONFIG GET databases - Get databases number INFO keys ...