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 ...
随机推荐
- ATM系统和购物车系统 不需要文件支撑
目录 ATM系统 购物车系统 ATM系统 #coding=utf8 #Version:python 3.6.4 #Tools:Python 2019.9.7 _data_ = '2019/9/7/01 ...
- 覆盖equals时请遵守通用约定
Object类中非final修饰的方法有equals().hashCode().toString().finalize().clone()1.equals()方法不需要被覆盖的情况:1)实例化的对象只 ...
- SQL SERVER 2008 R2 插入数据非常慢
表是5字段int类型,第一个字段是主健,自增字段 表结构: id int Uncheckedbillno bigint Uncheckedopid int Checkedbillopid int ...
- Liferay如何连接本地的数据库
Liferay自带的数据库非常迷你,一般就是玩玩的. 在真实的开发过程中,我们往往需要把它与我们本地的数据库相连. 有3中方法,我在这里就只介绍我自己最喜欢的方法啦.连的是mysql 1.在Lifer ...
- 笔记:OSAL st 宏学习 do { x } while (__LINE__ == -1)
笔记:OSAL st 宏学习 do { x } while (LINE == -1) #define st(x) do { x } while (__LINE__ == -1) 这段的意思是让代码可以 ...
- Docker Remote API使用准备
1 修改配置文件 CentOS: /etc/sysconfig/docker Ubuntu: /etc/init/docker.conf 1.添加: DOCKER_OPTS='-H tcp://0.0 ...
- 【JZOJ4893】【NOIP2016提高A组集训第15场11.14】过河
题目描述 数据范围 解法 由于同一个点,同一个圆盘最多只会走一次. 把(i,j)当作一个点,表示第i个点,放第i个圆盘. 那么就可以使用最短路. 时间复杂度为O(n4∗k). 事实上存在冗余圆盘,一个 ...
- 用预编译包安装zabbix-agent
如果主机无法上网,安装rpm又缺少依赖时,可以通过预编译包进行安装zabbix-agent,下载地址 https://www.zabbix.com/download 下载后,执行如下命令: wget ...
- 网络请求之jsonp封装
首先介绍下jsonp原理 浏览器因为同源策略的限制,在不同源的服务器通过我们传统axios是不能直接用来请求数据的(忽略代理),而src标签则不受同源策略的影响,所以我们需要动态的创建带有src的标签 ...
- Spring中配置DataSource数据源的几种选择
从JNDI获得DataSource. 从第三方的连接池获得DataSource. 使用DriverManagerDataSource获得DataSource. 一.从JNDI获得DataSource ...