CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)
•参考资料
•题意
由 n个1和m个-1组成的 $C_{n+m}^{n}$ 个序列;对所有序列的最大前缀和求和;
并规定最大前缀和最小是
0;
•题解
定义 $(i,j)$ 表示序列由 i 个 1,j 个 -1 组成;
$(i,j)$ 共有 $C_{i+j}^{i}$ 种不同的组合方式;
$(i-1,j)$ 共有 $C_{i+j-1}^{i-1}$ 种不同的组合方式;
$(i,j-1)$ 共有 $C_{i+j-1}^{i}$ 种不同的组合方式;
如果同时在 $(i-1,j)$ 的 $C_{i+j-1}^{i-1}$ 和 $(i,j-1)$ 的 $C_{i+j-1}^{i}$ 种组合方式的末尾或开头分别插入 1 或 -1;
那便是 $(i,j)$ 的不同的组合方式的种类数,即 $C_{i+j}^{i}=C_{i+j-1}^{i-1}+C_{i+j-1}^{i}$;
根据 n,m 的范围($\leq 2000$),考虑用 DP 解决这道题目;
首先,定义 $dp[i][j]$ 表示由 $(i,j)$ 组成的 $C_{i+j}^{i}$ 个序列,对所有序列的最大前缀和求和后的结果;
有上述前置知识,很容易想到 $(i,j)$ 可由 $(i-1,j)$ 和 $(i,j-1)$ 得到;
这也就是说,$dp[i][j]$ 可由 $dp[i-1][j]$ 和 $dp[i][j-1]$ 转移过来;
因为 $(i,j)$ 可由 $(i-1,j)$ 和 $(i,j-1)$ 的末尾或开头插入 1 或 -1 得到,那到底是在开头插入还是结尾插入呢?
因为题意让求的是前缀最大值之和,所以,我们考虑到在开头插入 1 或 -1:
- 在 $(i-1,j)$ 的开头插入 1,也就意味着这 $C_{i+j-1}^{i-1}$ 个序列的前缀最大值都会增加 1,那么
- $dp[i][j] += dp[i-1][j]+C_{i+j-1}^{i-1}$
- 在 $(i,j-1)$ 的开头插入 -1,意味着这 $C_{i+j-1}^{i}$ 个序列的前缀最大值会减少 1,那么
- $dp[i][j] += dp[i][j-1]-C_{i+j-1}^{i}+h[i][j-1]$
$h[i][j-1]$ 是干啥用的呢?
由题意,前缀最大值最小为 0,所以,在 $(i,j-1)$ 的开头插入 -1 的时候,前缀最大值为 0 的序列是不会减少 1 的;
我们就需要将这些多减掉的 1 在加上;
定义 $h[i][j]$ 表示 $(i,j)$ 的 $C_{i+j}^{i}$ 个序列种前缀最大值为 0 的个数;
同样 $h[i][j]$ 可由 $h[i-1][j]$ 和 $h[i][j-1]$ 转移过来;
考虑到 $h[i][j]$ 的定义,我们这次选择在 $(i-1,j)$ 和 $(i,j-1)$ 的结尾插入 1 或 -1;
很容易想到,如果 $i > j$,一定有 $h[i][j]=0$,所以,我们考虑 $i \le j$ 的情况;
因为是在结尾插入的,所以,前缀最大值第一次出现的位置是不会改变的,所以有 $h[i][j]=h[i-1][j]+h[i][j-1]$;
•Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=2e3+;
const int MOD=; int n,m;
ll dp[maxn][maxn];
ll h[maxn][maxn];
ll C[*maxn][*maxn]; void Init()
{
C[][]=;
for(int i=;i < *maxn;++i)
for(int j=;j <= i;++j)
{
if(j == || j == i)
C[i][j]=;
else
C[i][j]=C[i-][j]+C[i-][j-];
C[i][j] %= MOD;
} mem(h,);
for(int j=;j < maxn;++j)
h[][j]=;
for(int i=;i < maxn;++i)
for(int j=i;j < maxn;++j)
h[i][j]=(h[i-][j]+h[i][j-])%MOD; dp[][]=;
for(int i=;i < maxn;++i)
dp[i][]=i;
for(int j=;j < maxn;++j)
dp[][j]=;
for(int i=;i < maxn;++i)
for(int j=;j < maxn;++j)
{
dp[i][j]=(dp[i-][j]+C[i+j-][j])+(dp[i][j-]-C[i+j-][i]+h[i][j-]);
dp[i][j]=(dp[i][j]+MOD)%MOD;
}
} int main()
{
Init();
scanf("%d%d",&n,&m);
printf("%lld\n",dp[n][m]); return ;
}
CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)的更多相关文章
- CodeForces - 1204E Natasha, Sasha and the Prefix Sums (组合数学,卡特兰数扩展)
题意:求n个1,m个-1组成的所有序列中,最大前缀之和. 首先引出这样一个问题:使用n个左括号和m个右括号,组成的合法的括号匹配(每个右括号都有对应的左括号和它匹配)的数目是多少? 1.当n=m时,显 ...
- Codeforces Round #581 (Div. 2)-E. Natasha, Sasha and the Prefix Sums-动态规划+组合数学
Codeforces Round #581 (Div. 2)-E. Natasha, Sasha and the Prefix Sums-动态规划+组合数学 [Problem Description] ...
- [CF1204E]Natasha,Sasha and the Prefix Sums 题解
前言 本文中的排列指由n个1, m个-1构成的序列中的一种. 题目这么长不吐槽了,但是这确实是一道好题. 题解 DP题话不多说,直接状态/变量/转移. 状态 我们定义f表示"最大prefix ...
- E. Natasha, Sasha and the Prefix Sums
http://codeforces.com/contest/1204/problem/E 给定n个 1 m个 -1的全排 求所有排列的$f(a) = max(0,max_{1≤i≤l} \sum_{j ...
- CF1204E Natasha, Sasha and the Prefix Sums(组合数学)
做法一 \(O(nm)\) 考虑\(f(i,j)\)为i个+1,j个-1的贡献 \(f(i-1,j)\)考虑往序列首添加一个\(1\),则贡献\(1\times\)为序列的个数:\(C(j+i-1,i ...
- CF1204E Natasha, Sasha and the Prefix Sums (卡塔兰数推理)
题面 题解 把题意变换一下,从(0,0)走到(n,m),每次只能网右或往上走,所以假设最大前缀和为f(n),那么走的时候就要到达但不超过 y = x-f(n) 这条线, 我们可以枚举答案,然后乘上方案 ...
- CodeForces 837F - Prefix Sums | Educational Codeforces Round 26
按tutorial打的我血崩,死活挂第四组- - 思路来自FXXL /* CodeForces 837F - Prefix Sums [ 二分,组合数 ] | Educational Codeforc ...
- Educational Codeforces Round 26 [ D. Round Subset ] [ E. Vasya's Function ] [ F. Prefix Sums ]
PROBLEM D - Round Subset 题 OvO http://codeforces.com/contest/837/problem/D 837D 解 DP, dp[i][j]代表已经选择 ...
- Codeforces 837F Prefix Sums
Prefix Sums 在 n >= 4时候直接暴力. n <= 4的时候二分加矩阵快速幂去check #include<bits/stdc++.h> #define LL l ...
随机推荐
- No.2 Verilog 模块和描述风格
2-1 模块 Verilog语言基本的描述单元----模块,模块是用来描述某个设计的功能或结构,以及它与其它外部模块进行通信的端口. module module_name(port_list); De ...
- 如何mock https请求
最近在测试项目过程当中,遇到客户端mock https请求的场景,但是默认用charles抓取出来的https请求是乱码的,对于这类请求如何来mock,有以下2种方式: 1.这里有篇http://co ...
- hdu1907 尼姆博弈
尼姆博弈的性质. 最后一个取输.若a1^a2^a3...^a4=0表示利他态T,不然为利己态S.充裕堆:1个堆里的个数大于2.T2表示充裕堆大于等于2,T1表示充裕堆大于等于1,T0表示无充裕堆.S2 ...
- 巨蟒python全栈开发-第11阶段 ansible_project6
今日大纲: 1.计划任务前端页面 2.计划任务新增实现 3.计划任务编辑 4.项目详情 5.文件上传 6.replace模块介绍 1.计划任务前端页面 2.计划任务新增实现 3.计划任务编辑 4.项目 ...
- iOS 11 适配UIWebView,页面下移20的问题
方案1: AppDelegate文件 didFinishLaunchingWithOptions()中添加如下代码 if (@available(iOS 11.0, *)) { [[UIScrollV ...
- 伪元素 before 和 after 各种妙用
大家可能对伪类和伪元素有点迷糊,在介绍具体用法之前,简单介绍下伪类和伪元素.伪类大家听的多了,伪元素可能听到的不是那么频繁,其实 CSS 对这两个是有区分的. 这里整理总结下: 有时你会发现伪类元素使 ...
- @NOIP2018 - D2T3@ 保卫王国
目录 @题目描述@ @题解@ @代码@ @题目描述@ Z 国有n座城市,n−1 条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻 ...
- 15-2 mysql的数据类型
一.整数类型 整数类型:TINYINT SMALLINT MEDIUMINT INT BIGINT 作用:存储年龄,等级,id,各种号码等 ============================== ...
- 04Top K算法问题
本章阐述寻找最小的k个数的反面,即寻找最大的k个数,尽管寻找最大的k个树和寻找最小的k个数,本质上是一样的.但这个寻找最大的k个数的问题的实用范围更广,因为它牵扯到了一个Top K算法问题,以及有关搜 ...
- Linux系统服务及软件包的管理
要点回顾 free命令查看内存 整理buffer与cache的作用 1.buffer(缓冲) 是为了提高内存和硬盘(或其他I/O设备)之间的数据交换的速度而设计的. 2.cache(缓存) 从CPU ...