[bzoj4824][洛谷P3757][Cqoi2017]老C的键盘
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的键盘的更多相关文章
- 洛谷 P3757 [CQOI2017]老C的键盘
题面 luogu 题解 其实就是一颗二叉树 我们假设左儿子小于根,右儿子大于根 考虑树形\(dp\) \(f[u][i]\)表示以\(u\)为根的子树,\(u\)为第\(i\)小 那么考虑子树合并 其 ...
- 洛谷P3757 [CQOI2017]老C的键盘
传送门 首先可以直接把整个序列建成一个完全二叉树的结构,这个应该都看得出来 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小 ...
- Luogu P3757 [CQOI2017]老C的键盘
题目描述 老C的键盘 题解 显然对于每个数 x 都有唯一对应的 \(x/2\) , 然而对于每个数 x 却可以成为 \(x*2\) 和 \(x*2+1\) 的对应数 根据这一特性想到了啥??? 感谢l ...
- [bzoj4823][洛谷P3756][Cqoi2017]老C的方块
Description 老 C 是个程序员. 作为一个懒惰的程序员,老 C 经常在电脑上玩方块游戏消磨时间.游戏被限定在一个由小方格排成的R行C列网格上 ,如果两个小方格有公共的边,就称它们是相邻的, ...
- 洛谷$P3756\ [CQOI2017]$老$C$的方块 网络流
正解:网络流 解题报告: 传送门$QwQ$ 看到不能出现给定的讨厌的图形,简单来说就,特殊边两侧的方格不能同时再连方格. 所以如果出现,就相当于是四种方案?就分别炸四个格子. 然后冷静分析一波之后发现 ...
- [BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数
4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 218 Solved: 171[Submit][Statu ...
- [BZOJ4824][CQOI2017]老C的键盘(树形DP)
4824: [Cqoi2017]老C的键盘 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 193 Solved: 149[Submit][Statu ...
- [CQOI2017]老C的键盘
[CQOI2017]老C的键盘 题目描述 额,网上题解好像都是用的一大堆组合数,然而我懒得推公式. 设\(f[i][j]\)表示以\(i\)为根,且\(i\)的权值为\(j\)的方案数. 转移: \[ ...
- BZOJ4813或洛谷3698 [CQOI2017]小Q的棋盘
BZOJ原题链接 洛谷原题链接 贪心或树形\(DP\)都可做,但显然\(DP\)式子不好推(因为我太菜了),所以我选择贪心. 很显然从根出发主干走最长链是最优的,而剩下的点每个都需要走两步,所以用除去 ...
随机推荐
- H3C配置Hybrid端口
- Linux 内核中的数据类型
在我们进入更高级主题之前, 我们需要停下来快速关注一下可移植性问题. 现代版本的 Linux 内核是 高度可移植的, 它正运行在很多不同体系上. 由于 Linux 内核的多平台特性, 打算做认真使用的 ...
- centos7 teamviewer
Step 1: Install the prerequisites. # yum install glibc alsa-lib freetype libICE libSM libX11 libXau ...
- codeforces 11D(状压dp)
传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...
- Popup a window before the MainWindow
protected override void OnStartup(StartupEventArgs e) { Window w = new Window(); w.ShowDialog(); bas ...
- 本地安装配置Gradle及IDEA使用本地Gradle
一.下载Gradle 下载地址:http://services.gradle.org/distributions/ 下载版本的bin.zip 二.配置环境变量 三.验证 在cmd模式下查看 ...
- 查漏补缺:2020年搞定SpringCloud面试(含答案和思维导图)
前言 Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据监控等,都 ...
- 正基AP6212固件
需要正基技术资料联系我 QQ507014762 电话17666215391 #AP6212_NVRAM_V1.0.1_20160606 2.4 GHz, 20 MHz BW modeThe fo ...
- 007 Ceph手动部署单节点
前面已经介绍了Ceph的自动部署,本次介绍一下关于手动部署Ceph节点操作 一.环境准备 一台虚拟机部署单节点Ceph集群 IP:172.25.250.14 内核: Red Hat Enterpris ...
- Google Vision OCR
Google Vision OCR 爬坑建议 首先安装 Google Vision shell composer require google/cloud-vision 第一次使用的时候真的遇到的问题 ...