博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ4824][CQOI2017]老C的键盘(树形DP)
阅读量:4658 次
发布时间:2019-06-09

本文共 2413 字,大约阅读时间需要 8 分钟。

4824: [Cqoi2017]老C的键盘

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 193  Solved: 149
[][][]

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 。

HINT

Source

[ ][ ][ ]

完全二叉树反而好做些,且数据开到了$O(n^4)$都能过的范围,直接套上一题的式子即可。

1 #include
2 #include
3 #include
4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 using namespace std; 6 7 const int N=210,mod=1000000007; 8 char s[N]; 9 int n,a[N],sum[N][N],sz[N],f[N][N],g[N],C[N][N];10 11 void dfs(int x){12 f[x][1]=sum[x][1]=sz[x]=1;13 for (int s=x<<1; s<=((x<<1)|1); s++){14 if (s>n) return; dfs(s);15 memset(g,0,sizeof(g));16 if (a[s]==2){17 rep(i,1,sz[x]) if (f[x][i]) rep(j,0,sz[s]) if (sum[s][j])18 g[i+j]=(g[i+j]+1ll*f[x][i]*sum[s][j]%mod*C[i+j-1][i-1]%mod*C[sz[x]-i+sz[s]-j][sz[x]-i]%mod)%mod;19 }else{20 rep(i,1,sz[x]) if (f[x][i]) rep(j,0,sz[s])21 g[i+j]=(g[i+j]+1ll*f[x][i]*(sum[s][sz[s]]-sum[s][j]+mod)%mod*C[i+j-1][i-1]%mod*C[sz[x]-i+sz[s]-j][sz[x]-i])%mod;22 }23 sz[x]+=sz[s];24 rep(i,1,sz[x]) f[x][i]=g[i],sum[x][i]=(sum[x][i-1]+g[i])%mod;25 }26 }27 28 int main(){29 freopen("keyboard.in","r",stdin);30 freopen("keyboard.out","w",stdout);31 scanf("%d",&n); scanf("%s",s+1);32 rep(i,0,n) C[i][0]=1;33 rep(i,1,n) rep(j,1,n) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;34 rep(i,2,n) if (s[i-1]=='<') a[i]=1; else a[i]=2;35 dfs(1); printf("%d\n",sum[1][sz[1]]);36 return 0;37 }

 

转载于:https://www.cnblogs.com/HocRiser/p/8708548.html

你可能感兴趣的文章
一个简单的PHP网站结构
查看>>
Redis 学习之简介及安装
查看>>
jsp简单的学习
查看>>
[LeetCode][JavaScript]Number of 1 Bits
查看>>
[LeetCode][JavaScript]Plus One
查看>>
C语言-06复杂数据类型-01数组
查看>>
vue 图片预览插件
查看>>
深入解析:分布式系统的事务处理经典问题及模型
查看>>
找工作——JVM内存管理
查看>>
【Flask】在Flask中使用logger
查看>>
好系统重装助手教你如何让win10系统快速开机
查看>>
linux开机启动
查看>>
BZOJ 1101 [POI2007]Zap 【莫比乌斯反演】
查看>>
SQL Server-The target principal name is incorrect. Cannot generate SSPI context
查看>>
AS3全局与局部坐标转换
查看>>
Java内部类详解
查看>>
初识Twisted(一)
查看>>
linux 软件安装篇
查看>>
Sql server数据库大小写敏感设置
查看>>
JAVA多线程-内存模型、三大特性、线程池
查看>>