【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 ...
随机推荐
- buf.readInt8()
buf.readInt8(offset[, noAssert]) offset {Number} 0 noAssert {Boolean} 默认:false 返回:{Number} 从该 Buffer ...
- Django DTL模板语法中的循环
from django.shortcuts import render def index(request): context={ 'books':[ '5年高考3年模拟', '家猪养殖与配种', ' ...
- Balanced Numbers(数位dp)
Description Balanced numbers have been used by mathematicians for centuries. A positive integer is c ...
- [linux]centos7下解决yum install mysql-server没有可用包
第一步:安装从网上下载文件的wget命令 [root@master ~]# yum -y install wget 第二步:下载mysql的repo源 [root@master ~]# wget ht ...
- RequestMapping_HiddenHttpMethodFilter 过滤器
[REST] 1.REST:即Representational State Transfer.(资源)表现层状态转化.是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以得 ...
- Apache 流框架 Flink,Spark Streaming,Storm对比分析(2)
此文已由作者岳猛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2.Spark Streaming架构及特性分析 2.1 基本架构 基于是spark core的spark s ...
- Uva1103 Ancient Messages
题意:识别图中的象形文字.但是,图形可以任意的拉伸,但不能拉断. 分析:这种题如果图形没有特征是不可做类型的题,不过观察图形可以发现每个图形中的洞的数量是一定的,我们只需要数出每一个封闭图形的洞数就能 ...
- - > 最大公约数(辗转相除法)和最小公倍数(公式法)
最大公约数 #include<iostream> using namespace std; int a,b; int gcd(int x,int y){ return x==0?y:gcd ...
- 微软消息队列MessageQueue(MQ)
首先本地安装微软的消息队列服务器. 基础类: namespace Core.MessageQueueTest { public class TestQueue : IDisposable { prot ...
- 创建NetCore2.2 Web项目+EFCore+SQLServer
在空余时间学习下NetCore,记录日常,供参考. 1.确保已下载安装NetCore2.2SDK 环境,下载地址:https://dotnet.microsoft.com/download/dotne ...