「题解报告」CF1067A Array Without Local Maximums
大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解
动态规划三部曲:确定状态,转移方程,初始状态和答案。
——神仙 @akicc
第一步 确定状态
\(f_{i,j,k}(k\in\{0,1,2\})\)表示第 \(i\) 个数选为 \(j\) 且和前一个数是小于/等于/大于(\(k=0\) 是大于,\(k=1\) 是等于,\(k=2\) 是小于)的关系时的方案数。
第二步 转移方程
把三种关系分开讨论:
- \(k=0\),比上一个大,它的方案数就是上一个数选的比它小的数的方案数和;
- \(k=1\),由于和上一个数相同,它的方案数就是上一个数的方案数和;
- \(k=2\),比上一个小,它的方案数就是上一个数选的比它大的数的方案数和,但是为了防止上一个数比相邻的数都大,我们要去掉上一个数比上上个数大的方案数。
那么我们的转移方程就是:
\(f_{i,j,0}=\sum^{j-1}_{l=1}f_{i-1,l,0}+f_{i-1,l,1}+f_{i-1,l,2}\)
\(f_{i,j,1}=f_{i-1,j,0}+f_{i-1,j,1}+f_{i-1,j,2}\)
\(f_{i,j,2}=\sum^{200}_{l=j+1}f_{i-1,l,1}+f_{i-1,l,2}\)
如果 \(a_i=-1\) 则 \(1\le j\le 200\),否则 \(j=a_i\) 。
直接求和会超时,我们可以使用前缀和优化。
第三步 初始状态和答案
如果第二个数取得比第一个数小就不符合题目要求了,而第一个数只有一种取法,所以我们让 \(f_{1,j,0}=1\),就可以让 \(f_{2,j,2}\) 取不到方案数了!
如果最后一个数比倒数第二个数大,也不符合题意,所以我们在取答案的时候不能取 \(f_{n-1,j,0}\) 。
代码
#include <bits/stdc++.h>
#define _for(i,a,b) for(int i=a;i<=b;++i)
#define for_(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=1e5+10,M=998244353;
ll n,a[N],f[N][205][3],ans;
void pre(){
if(a[1]==-1)_for(i,1,200)f[1][i][0]=1;
else f[1][a[1]][0]=1;
}void dp(){
_for(i,2,n){
int s=0;
_for(j,1,200){
if(a[i]==-1||a[i]==j)f[i][j][0]=s%M,f[i][j][1]=(f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2])%M;
s=(s+f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2])%M;
}s=0;
for_(j,200,1){
if(a[i]==-1||a[i]==j)f[i][j][2]=s%M;
s=(s+f[i-1][j][1]+f[i-1][j][2])%M;
}
}
}int main(){
scanf("%lld",&n);
_for(i,1,n)scanf("%lld",&a[i]);
pre(),dp();
_for(i,1,200)ans=(ans+f[n][i][1]+f[n][i][2])%M;
printf("%lld",ans);
//system("pause");
return 0;
}
「题解报告」CF1067A Array Without Local Maximums的更多相关文章
- 「题解报告」 P3167 [CQOI2014]通配符匹配
「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...
- 「题解报告」P4577 [FJOI2018]领导集团问题
题解 P4577 [FJOI2018]领导集团问题 题解区好像没有线段树上又套了二分的做法,于是就有了这片题解. 题目传送门 怀着必 WA 的决心交了两发,一不小心就过了. 题意 求一个树上最长不下降 ...
- 「题解报告」P2154 虔诚的墓主人
P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...
- 「题解报告」SP16185 Mining your own business
题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
- 「题解报告」Blocks
P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...
- 「题解报告」P3354
P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...
- 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
- 【计数dp】Array Without Local Maximums
参考博客:[CF1068D]Array Without Local Maximums(计数DP) [题意] n<=1e5 dp[i][j][k]表示当前第i个数字为j,第i-1个数字与第i个之间 ...
- codeforces 1068d Array Without Local Maximums dp
题目传送门 题目大意:给出一个长度为n的数组,这个数组有的数是给出的,有的数是固定的,且范围都在[1,200]之间,要求这个数组中,每一个数字都小于等于 前后两个数字的最大值,求方案数mod p. 思 ...
随机推荐
- .NET中的迭代器(Iterator)
更新记录 本文迁移自Panda666原博客,原发布时间:2021年6月30日. 一.迭代器介绍 C#2.0开始,我们可以使用迭代器(iterator).编译器自动把我们定义的迭代器生成 可枚举类型 或 ...
- Conda 虚拟环境移植
这时候你应该位于具有待移植的环境的服务器: 1 进入你要移植的环境 conda activate your_env 2 导出当前conda环境到某个文件(文件名字可以自定义) conda env ex ...
- Java 泛型中的通配符
本文内容如下: 1. 什么是类型擦除 2.常用的 ?, T, E, K, V, N的含义 3.上界通配符 < ?extends E> 4.下界通配符 < ?super E> 5 ...
- element ui 自定义主题失败(primordials is not defined)
卸载: 1.卸载cnpm npm uninstall cnpm -g 2.卸载vue-cli npm uninstall @vue/cli -g 3.卸载nodejs和删除文件 C:\Program ...
- java SWT中Label实时刷新当前时间
同样最近在开发swt的一个项目,业务中的一个功能模块类似百度网盘的上传进度条 0/80. 即已上传0个,总共80个.效果展示要的就是实时刷新,2/80呀,15/80呀,针对这个,就有了这篇文章. 下面 ...
- java.Scanner 拓展用法
package study5ran2yl.study; import java.util.Scanner; public class demo11 { public static void main( ...
- day01 Java_JVM,JCR,JDK
精华笔记: java开发环境: 编译运行过程: 编译期:.java源文件,经过编译,生成.class字节码文件 运行期:JVM加载.class并运行.class(0和1) 特点:跨平台.一次编程到处使 ...
- 图的存储结构大赏------数据结构C语言(图)
图的存储结构大赏------数据结构C语言(图) 本次所讲的是常有的四种结构: 邻接矩阵 邻接表 十字链表 邻接多重表 邻接矩阵 概念 两个数组,一个表示顶点的信息,一个用来表示关联的关系. 如果是无 ...
- 常用的函数式接口_Predicate接口和常用的函数式借楼_Predicate_默认方法and
package com.yang.Test.PredicateStudy; import java.util.function.Predicate; /** * java.util.function. ...
- linux 文件存放目录
Linux不靠文件扩展名区分文件类型(windous病毒和木马不能在linux里面运行) 所有的存储设备都必须挂载之后才能使用(包括硬盘,U盘和光盘),例如给它手工给它分配盘符 Linux所有内容以文 ...