Description###

老 C 是个程序员。

作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序

在某种神奇力量的驱使之下跑得非常快。小 Q 也是一个程序员。有一天他悄悄潜入了老 C 的家中,想要看看这个

键盘究竟有何妙处。他发现,这个键盘共有n个按键,这n个按键虽然整齐的排成一列,但是每个键的高度却互不相同

。聪明的小 Q 马上将每个键的高度用 1 ~ n 的整数表示了出来,得到一个 1 ~ n 的排列 h1, h2,..., hn 。为了

回去之后可以仿造一个新键盘(新键盘每个键的高度也是一个 1 ~ n 的排列),又不要和老 C 的键盘完全一样,小 Q

决定记录下若干对按键的高度关系。作为一个程序员,小 Q 当然不会随便选几对就记下来,而是选了非常有规律的

一些按键对:对于 i =2,3, ... , n,小 Q 都记录下了一个字符<或者>,表示 h_[i/2] < h_i 或者h _[i/2] > h_i

。于是,小 Q 得到了一个长度为n ? 1的字符串,开开心心的回家了。现在,小 Q 想知道满足他所记录的高度关系的

键盘有多少个。虽然小 Q 不希望自己的键盘和老 C 的完全相同,但是完全相同也算一个满足要求的键盘。答案可

能很大,你只需要告诉小 Q 答案 mod 1,000,000,007 之后的结果即可。

Input###

输入共 1 行,包含一个正整数 n 和一个长度为 n ? 1 的只包含<和>的字符串,分别表示键

盘上按键的数量,和小 Q 记录的信息,整数和字符串之间有一个空格间隔。

Output###

输出共 1 行,包含一个整数,表示答案 mod 1,000,000,007后的结果。

Sample Input###

5 <>><

Sample Output###

3

共5个按键,第1个按键比第2个按键矮,第1个按键比第3个按键高,第2个按键比第4个

按键高,第2个按键比第5个按键矮。

这5个按键的高度排列可以是 2,4,1,3,5 , 3,4,1,2,5 , 3,4,2,1,5 。


简要题解##

根据题目描述按键高度关系连边,恰形成一棵二叉树。

树形dp+组合 求解。


想法##

看到这道题,我的第一想法是根据高度<或>连边,小的向大的连一条边,形成有向图。

题目要求的便是这个有向图拓扑排序的方案数。

然而这个东西并不太好搞……

于是,又翻题解……

考虑题中所说\(h_i\) 与 \(h_{i/2}\) 比较,发现比较关系可以形成一棵树。

假设某个点的两个子树已各自计算出满足要求的方案数,那这两个子树在各自顺序保持不变时相互顺序怎么改变都仍满足要求。

把当前点插进来只需满足它与左右子的大小关系。

故树形dp,状态f[i][j]表示i在以i为根的子树中排第j位的方案数。

求解f[i][j]时枚举排在i前面的j-1位中有多少位在左子子树(这时要注意i与其左右子的大小关系),记下f[][]的前后缀和,带上组合数瞎搞搞就出来了……

为啥感觉这道题出的有点为树形dp而树形dp呢,感觉不太自然。


代码##

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> #define P 1000000007 using namespace std; typedef long long ll;
const int N = 105; int d[N],f[N][N],sum[2][N][N];
int size[N];
int n; int C[N][N];
void getC(){
C[0][0]=1;
for(int i=1;i<=n;i++){
C[i][0]=1;
for(int j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%P; /**/
C[i][i]=1;
}
} int main()
{
char ch[N];
scanf("%d",&n);
scanf("%s",ch);
for(int i=2;i<=n;i++)
d[i]=(ch[i-2]=='>'); getC();
//dp
for(int i=n;i>0;i--){
if(i*2>n){ //leaf
f[i][1]=sum[0][i][1]=sum[1][i][1]=1;
size[i]=1;
continue;
}
if(i*2+1>n){ //single son
size[i]=size[i*2]+1;
for(int j=1;j<=size[i];j++){
if(d[i<<1]) f[i][j]+=sum[0][i<<1][j-1];
else f[i][j]+=sum[1][i<<1][j];
}
for(int j=1;j<=size[i];j++)
sum[0][i][j]=((ll)sum[0][i][j-1]+f[i][j])%P;
for(int j=size[i];j>0;j--)
sum[1][i][j]=((ll)sum[1][i][j+1]+f[i][j])%P;
continue;
}
size[i]=size[i*2]+size[i*2+1]+1; //double son
for(int j=1;j<=size[i];j++){
for(int k1=0;k1<j && k1<=size[i<<1];k1++){
int k2=j-1-k1,s1,s2;
if(k2>size[i*2+1]) continue;
if(d[i<<1]) s1=sum[0][i<<1][k1];
else s1=sum[1][i<<1][k1+1];
if(d[(i<<1)+1]) s2=sum[0][(i<<1)+1][k2];
else s2=sum[1][(i<<1)+1][k2+1];
f[i][j]=((ll)f[i][j]+(ll)((((ll)s1*s2)%P*C[j-1][k1])%P*C[size[i]-j][size[i<<1]-k1])%P)%P;
}
}
for(int j=1;j<=size[i];j++)
sum[0][i][j]=((ll)sum[0][i][j-1]+f[i][j])%P;
for(int j=size[i];j>0;j--)
sum[1][i][j]=((ll)sum[1][i][j+1]+f[i][j])%P;
} printf("%d\n",sum[0][1][size[1]]); return 0;
}

[bzoj4824][洛谷P3757][Cqoi2017]老C的键盘的更多相关文章

  1. 洛谷 P3757 [CQOI2017]老C的键盘

    题面 luogu 题解 其实就是一颗二叉树 我们假设左儿子小于根,右儿子大于根 考虑树形\(dp\) \(f[u][i]\)表示以\(u\)为根的子树,\(u\)为第\(i\)小 那么考虑子树合并 其 ...

  2. 洛谷P3757 [CQOI2017]老C的键盘

    传送门 首先可以直接把整个序列建成一个完全二叉树的结构,这个应该都看得出来 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小 ...

  3. Luogu P3757 [CQOI2017]老C的键盘

    题目描述 老C的键盘 题解 显然对于每个数 x 都有唯一对应的 \(x/2\) , 然而对于每个数 x 却可以成为 \(x*2\) 和 \(x*2+1\) 的对应数 根据这一特性想到了啥??? 感谢l ...

  4. [bzoj4823][洛谷P3756][Cqoi2017]老C的方块

    Description 老 C 是个程序员. 作为一个懒惰的程序员,老 C 经常在电脑上玩方块游戏消磨时间.游戏被限定在一个由小方格排成的R行C列网格上 ,如果两个小方格有公共的边,就称它们是相邻的, ...

  5. 洛谷$P3756\ [CQOI2017]$老$C$的方块 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 看到不能出现给定的讨厌的图形,简单来说就,特殊边两侧的方格不能同时再连方格. 所以如果出现,就相当于是四种方案?就分别炸四个格子. 然后冷静分析一波之后发现 ...

  6. [BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数

    4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 218  Solved: 171[Submit][Statu ...

  7. [BZOJ4824][CQOI2017]老C的键盘(树形DP)

    4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 193  Solved: 149[Submit][Statu ...

  8. [CQOI2017]老C的键盘

    [CQOI2017]老C的键盘 题目描述 额,网上题解好像都是用的一大堆组合数,然而我懒得推公式. 设\(f[i][j]\)表示以\(i\)为根,且\(i\)的权值为\(j\)的方案数. 转移: \[ ...

  9. BZOJ4813或洛谷3698 [CQOI2017]小Q的棋盘

    BZOJ原题链接 洛谷原题链接 贪心或树形\(DP\)都可做,但显然\(DP\)式子不好推(因为我太菜了),所以我选择贪心. 很显然从根出发主干走最长链是最优的,而剩下的点每个都需要走两步,所以用除去 ...

随机推荐

  1. Teleport ultra/IDM(Internet Download Manager)

    神器扒网站——teleport ultra IDM(Internet Download Manager) 在平时的开发或者学习的过程中,我们难免会看到一些让人心动的网站,于是自己想把它搞下来,自己手工 ...

  2. vc得到屏幕的当前分辨率方法

    vc得到屏幕的当前分辨率方法:1.Windows API调用int width = GetSystemMetrics ( SM_CXSCREEN ); int height= GetSystemMet ...

  3. ssh批量免密

    expect命令在linux下实现批量ssh免密 发布时间:2017-11-27 08:41:39 投稿:laozhang 本次文章主要给大家讲解了在linux系统下用expect命令实现批量ssh免 ...

  4. boostrap-非常好用但是容易让人忽略的地方【4】:Font Awesome

    font-awesome基本用法 官方代码传送门 font-awesome在bootstrap中的特殊用法(这个才是重点) 要点归纳1(官方) 官方代码传送门 要点归纳2(我的) <a href ...

  5. Visio数据视觉化处理

    形状数据的查看的两种方式 定义形状数据:右键单击数据窗口 打勾的代表可以显示 其他没有打勾的就必须要在开发模式才会显示出来 开发模式就是打开开发工具面板 注意其中类型的设置 类型与格式是一一对应的 不 ...

  6. Spring注解之@Autowired、@Qualifier、@Resource、@Value

    前言 @Autowired.@Qualifier.@Resource.@Value四个注解都是用于注入数据的,他们的作用就和在xml配置文件中的bean标签中写一个标签的作用是一样的!本篇中特别要讲解 ...

  7. bug(一)环境问题

    1.项目开发完成,部署到服务器进行测试,遇到一个问题: 同样的接口,同样的数据库表,同样的功能,得到不同的查询结果 具体如下图: 可以看到一个是有值的,一个是无值的,断点调试会发现所以的状态都是对的, ...

  8. C++版本的UnEscape 解析\uxxxx\uxxxx编码字符

    解析类似于这种Unicode编码格式的字符串 \u5b55\u5987\u88c5\u590f\u88c52018\u65b0\u6b3e\u5bbd\u677e\u77ed\u8896\u4e2d\ ...

  9. 【题解】Uoj#30 Tourist(广义圆方树+树上全家桶)

    [题解]Uoj#30 Tourist(广义圆方树+树上全家桶) 名字听起来很霸气其实算法很简单.... 仙人掌上的普通圆方树是普及题,但是广义圆方树虽然很直观但是有很多地方值得深思 说一下算法的流程: ...

  10. $vjudge-$搜索专题题解

    退役了,刷点儿无脑水题$bushi$放松下$QwQ$ 然后先放个链接,,,$QwQ$ $A$ 虽然是英文但并不难$get$题目大意?就说给定一个数独要求解出来,$over$ 昂显然直接$dfs$加剪枝 ...