这题在网上找不到题解,硬写一下午终于写出来了……

题目:

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]代码(卡特兰数)的更多相关文章

  1. BZOJ2944 : [Poi2000]代码

    对于根,要让它的排名尽量小,也就是要让右子树的点数尽量多. 于是从大到小枚举右子树的点数,用Catalan数计算方案数,直到找到相应的右子树的点数为止. 此时根的排名已经确定,接下来要让左子树的代码的 ...

  2. 卡特兰数(Catalan)

    卡特兰数又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现在各种计数问题中出现的数列.由以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)命名,其前几项为 : 1, 2, ...

  3. HDU 5673 Robot ——(卡特兰数)

    先推荐一个关于卡特兰数的博客:http://blog.csdn.net/hackbuteer1/article/details/7450250. 卡特兰数一个应用就是,卡特兰数的第n项表示,现在进栈和 ...

  4. HDU 1023 Traning Problem (2) 高精度卡特兰数

    Train Problem II Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Sub ...

  5. hdu 1023 卡特兰数+高精度

    Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. HDU 1023 Train Problem II (卡特兰数,经典)

    题意: 给出一个数字n,假设火车从1~n的顺序分别进站,求有多少种出站序列. 思路: 卡特兰数的经典例子.n<101,用递推式解决.需要使用到大数.n=100时大概有200位以下. #inclu ...

  7. 2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

    题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展g ...

  8. poj 1095 Trees Made to Order 卡特兰数

    这题用到了卡特兰数,详情见:http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html 解体思路详见:http://blog.csdn. ...

  9. 【HDU 5370】 Tree Maker(卡特兰数+dp)

    Tree Maker Problem Description Tree Lover loves trees crazily. One day he invents an interesting gam ...

随机推荐

  1. Spring核心技术(三)——Spring的依赖及其注入(续)

    本文将继续前文,针对依赖注入的细节进行描述 依赖注入细节 如前文所述,开发者可以通过定义Bean的依赖的来引用其他的Bean或者是一些值的,Spring基于XML的配置元数据通过支持一些子元素< ...

  2. Leetcode 123.买卖股票的最佳时机III

    买卖股票的最佳时机III 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与多笔交易(你 ...

  3. [K/3Cloud]在插件中根据条件取消表单打开过程

    新建一个类,继承自动态表单抽象插件类AbstractBillPlugIn,重写PreOpenForm. /// <summary> /// 销售订单 单据维护界面插件 /// </s ...

  4. IDEA中用jetty启动项目时,url 404

    问题背景:IDE:IDEA 语言:java 服务器:jetty 框架:nutz 问题描述: 按照nutz构建j2ee项目,配置projectStructor中的依赖,jre,jetty之后,部署,并通 ...

  5. [poj1678]I Love this Game!_博弈论

    I Love this Game! 题目大意:题目链接 注释:略. 想法: 开始的时候以为没法dp,结果...:a>0啊! 所以可以直接dp了啊! 状态:dp[i]表示先手选了a[i]的状态. ...

  6. BIV+CSS网页的标准化布局

    DIV用于搭建网站结构(框架),CSS用于创建网站表现(样式/美化) DIV+CSS模式设计网站的优势: 1.表现和内容分离. 2代码简洁,提高网页浏览速度. 3.易于维护,改版. 4.提高搜索引擎对 ...

  7. CString、char*与string的区别

    三者的区别 CString 是MFC或者ATL中的实现: string 是C++标准库中的实现: char* 为C编程中最常用的字符串指针,一般以’\0’为结束标志. string和CString均是 ...

  8. C# 运行CMD命令

    /// <summary> /// 运行CMD命令 /// </summary> /// <param name="cmd">命令</pa ...

  9. 【Android 开发实例】时间管理APP开发之数据库设计

    当然也能够先写界面什么的.可是,总认为先把数据库后台写好在写界面比較放心. 对于数据库的设计,我一開始没什么概念.甚至不知道怎样下手,一開始想着设计成几个表?有哪些字段? 最后用了两天时间,还是一无所 ...

  10. 安卓下载文件怎样更新UI进度

    曾经写过几篇关于下载的文章.总的来说是下面几点: 1.维护一个下载进程的Hashmap,key:使用Md5进行处理后的文件下载地址,value为下载的Task. 以防止下载反复.并将信息保存至数据库. ...