jzoj5342 赤壁情 (序列插入型dp,笛卡尔树新奇姿势dp)
来源:互联网 发布:第四套人民币淘宝 编辑:程序博客网 时间:2024/06/11 05:42
题面
很玄幻的一题dp.
现在有一块一块的子串,他们的相对顺序是已知的但最终一定不相邻 (也就是说中间至少有一个数)
考虑从小到大插入数字,每一个数字有3种基本转移
1. 在某个空隙新建一块,
2. 并入某块(放最左或最右)。
3. 合并相邻两块
贡献系数好算,比如说并入一块那么系数就是0,假如新开系数就是-2 (因为可以知道旁边是比他大的还是比他小的)
但是有一个问题,边界贡献比较特殊,所以要开两个特殊块:边界 L,R
顾名思义,规定边界的左右不能再放。
那么要加几条转移
1. 在某个空隙新建一块普通块
3. 新建L或R
4. 并入某普通块(放最左或最右)
5. 并入目前的最左或最右,并将其升级为L或R
(因为最终的最左或最右不一定小,要支持在他旁边插数)
6. 并入L或R
7. 合并相邻两块
这样我们状态就变成了
是
最终的答案就是sum f[n][k][1][1][1],最后再除上一个排列就得到概率了. (强行套上概率的,明明可以直接加mod,还是比较慢的缘故?)
这样为什么不会重呢? 考虑到一块中的元素是从小到大被加入的,每一块就相当于一颗笛卡尔树。转移的意义分别是
1. 在某个空隙新建一块, (以当前为根新建一棵)
2. 并入某块(放最左或最右)。 (以当前为根,将原有笛卡尔树视为左或右子树)
3. 合并相邻两块 (以当前为根,左右分别为两颗子树)
因为一个序列对应着的笛卡尔树只有一棵,在从小到大加入前提下,显然一棵笛卡尔树有且仅有一种构造方法。 因此是不重不漏的。
Demo
//#pragma GCC optimize(2)#include <cstdio>#include <iostream>#include <cstring>using namespace std;// typedef __float128 fff;typedef double fff;const int N=101;fff f[2][N][N*N][2][2];int n,m,k,e,o;int main() { freopen("river.in","r",stdin); freopen("river.out","w",stdout); cin>>n>>m>>k; e=n*n/2; f[o][0][e][0][0]=1; for (int i=0; i<n; i++) { memset(f[1-o],0,sizeof f[1-o]); for (int j=0; j<=i; j++) { if (n-i+1<j-1) break; for (int k=0; k<=e*2; k++) { for (int u=0; u<=1; u++) for (int v=0; v<=1; v++) { fff p = f[o][j][k][u][v]; if (p<1) continue; //create if (k-i>0) { if (!u) f[1-o][j+1][k-(i+1)][1][v]+=p; if (!v) f[1-o][j+1][k-(i+1)][u][1]+=p; if (k-2*i>0) f[1-o][j+1][k-2*(i+1)][u][v]+=p*(j+1-u-v); } //add if (j) { f[1-o][j][k][u][v]+=p*(j*2-u-v); //start-add if (!u) f[1-o][j][k+(i+1)][1][v]+=p; //end-add if (!v) f[1-o][j][k+(i+1)][u][1]+=p; //merge if (j>1) f[1-o][j-1][k+2*(i+1)][u][v]+=p*(j-1); } } } } o=1-o; } fff ans = 0; for (int i=m+e; i<=e*2; i++) ans+=f[o][1][i][1][1]; for (int i=1; i<=n; i++) ans/=i;// cout<<ans<<endl; printf("0."); for (int i=1; i<k; i++) { ans*=10; printf("%d",((int)ans)%10); } if ((int)(ans*100)%10>=5) printf("%d",(int)(ans*10)%10+1); else printf("%d",(int)(ans*10)%10);}
- jzoj5342 赤壁情 (序列插入型dp,笛卡尔树新奇姿势dp)
- 【JZOJ5342】【NOIP2017模拟9.2A组】赤壁情
- 【NOIP模拟】赤壁情(DP)
- DP新姿势
- 序列型DP
- 数位dp的一种姿势
- HDU 5125 序列型DP
- DP最大子序列
- poj1141 括号序列 dp
- DP 子序列问题
- poj 1050 序列dp
- 摆动序列(DP)
- HDOJ5256 序列变换(dp)
- 子序列个数(DP)
- 蓝桥杯 摆动序列 dp
- 求子序列 DP
- 航线设计 (序列DP)
- dp uva1626 括号序列
- HDU 5887 大体积 大价值 背包 搜索剪枝
- 编译原理与编译构造 课堂笔记1 导论
- Android的线程消息机制(Handler机制剖析)
- git 使用
- 什么是选择器?
- jzoj5342 赤壁情 (序列插入型dp,笛卡尔树新奇姿势dp)
- luogu1108
- HDU 1003:Max Sum(简单dp)
- 2017.09.02【NOIP提高组】模拟赛B组
- C 文件读写(以判断闰年为例)
- 一些笔试题小汇总
- ionic应用程序跳转其它网站地址实现(themeablebrowser)相当于WebView
- Python Challenge笔记
- struts2是单例的吗