P8810 [蓝桥杯 2022 国 C] 数组个数 题解
思路比较简单的一道题。
用的五维 dp,看到二维和三维的 dp 直接膜了 orz。
正文开始。
分析
不难看出 dp。
因为 \(b_i\) 的值只与 \(a_{i-1},a_i,a_{i+1}\) 有关,所以我们定义 \(b_i\) 被 \(a_{c_1},a_{c_2},...a_{c_p}\) 满足为在这些 \(a\) 中最大的一项恰好为 \(b_i\)。
用 \(dp_{i,j,0/1,0/1,z}\) 来表示此状态下的方案数。
其中:
- \(i\) 表示当前处于第 \(i\) 项。
- \(j\) 表示当前这一项选择 \(j\)。
- \(1/0\) 表示 \(b_i\) 是否被 \(a_{i-1},a_i\) 满足。
- \(1/0\) 表示 \(b_0\) 是否被 \(a_0,a_1\) 满足。
- \(z\) 表示 \(a_0\) 选择 \(z\)。
显然,\(a_i\) 的最大值就是 \(\min(b_{i-1},b_i,b_{i+1})\),又因为 \(b_i\le10\),所以 \(a_i\) 的最大值也是 \(10\)。
状态转移方程比较复杂。
如果 \(i>1\),那么我们需要枚举 \(a_i\) 和 \(a_{i-1}\)。
这时候存在两种情况:
- \(b_i\) 被 \(a_i,a_{i-1}\) 满足,此时应该更新 \(dp_{..,..,1,..,..}\) 的值。
- \(b_i\) 不被 \(a_i,a_{i-1}\) 满足,此时应该更新 \(dp_{..,..,0,..,..}\) 的值。
注意:在选择 \(a_i\) 的时候,\(b_{i-1}\) 必须被 \(a_{i-2},a_{i-1},a_i\) 满足,原因显然。
但当 \(i=1\) 时,应该单独讨论,因为 \(a_1\) 的选择会影响到 dp 数组的第 \(4\) 项,而 \(i\ge2\) 则不会。思路跟 \(i\ge2\) 的情况类似,不再赘述。
最后统计答案时,我们有几种情况:
- \(dp_{n-1,x,1,1,y}\),因为此时 \(b_{n-1}\) 和 \(b_0\) 已经被满足,而其它的 \(b\) 也都被满足,直接加上即可。
- \(dp_{n-1,x,0,1,y}\) 当 \(b_{n-1}\le y\) 时可以相加,因为 \(a\) 数组是环形的。
- \(dp_{n-1,x,1,0,y}\) 当 \(b_0\le x\) 时可以相加,原因同上。
最后,记得取模。
AC Code
臭长臭长的代码 qwq。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
const int MOD = 1e9 + 7;
int n;
int dp[N][11][2][2][11], b[N], am[N];
int st;
inline int nxt (int idx) {
return ((idx + 1) % n);
}
inline int pre (int idx) {
return ((idx - 1 + n) % n);
}
int m (int x) {
if (x < MOD) return x;
return x - MOD;
}
int main () {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
for (int i = 0;i < n;i++) cin >> b[i];
for (int i = 0;i < n;i++) am[i] = min(b[pre(i)], min(b[i], b[nxt(i)]));
for (int i = 0;i <= am[0];i++) if (i < b[0]) dp[0][i][0][0][i] = 1; else dp[0][i][1][1][i] = 1;
for (int x = 0;x <= am[0];x++) for (int st = 0;st <= 1;st++) for (int j = 0;j <= am[1];j++) {
if (j < b[1] && x < b[1]) {
if (j < b[0]) dp[1][j][0][st][x] += m(dp[0][x][0][st][x] + dp[0][x][1][st][x]), dp[1][j][0][st][x] = m(dp[1][j][0][st][x]);
else dp[1][j][0][1][x] += m(dp[0][x][0][st][x] + dp[0][x][1][st][x]), dp[1][j][0][1][x] = m(dp[1][j][0][1][x]);
}
else {
if (j < b[0]) dp[1][j][1][st][x] += m(dp[0][x][0][st][x] + dp[0][x][1][st][x]), dp[1][j][1][st][x] = m(dp[1][j][1][st][x]);
else dp[1][j][1][1][x] += m(dp[0][x][0][st][x] + dp[0][x][1][st][x]), dp[1][j][1][1][x] = m(dp[1][j][1][1][x]);
}
}
for (int i = 2;i < n;i++) {
int p = i - 1;
for (int x = 0;x <= am[0];x++) for (int st = 0;st <= 1;st++) {
for (int j = 0;j <= am[i];j++) {
for (int z = 0;z <= am[p];z++) {
if (j < b[i] && z < b[i]) {
if (j < b[p]) dp[i][j][0][st][x] += dp[p][z][1][st][x];else dp[i][j][0][st][x] += m(dp[p][z][0][st][x] + dp[p][z][1][st][x]);
dp[i][j][0][st][x] = m(dp[i][j][0][st][x]);
}
else {
if (j < b[p]) dp[i][j][1][st][x] += dp[p][z][1][st][x];
else dp[i][j][1][st][x] += m(dp[p][z][0][st][x] + dp[p][z][1][st][x]);
dp[i][j][1][st][x] = m(dp[i][j][1][st][x]);
}
}
}
}
}
int ans = 0;
for (int x = 0;x <= am[0];x++) for (int i = 0;i <= am[n - 1];i++) {
ans += dp[n - 1][i][1][1][x]; ans = m(ans);
if (i >= b[0]) ans += dp[n - 1][i][1][0][x];
if (x >= b[n - 1]) ans += dp[n - 1][i][0][1][x];
ans = m(ans);
}
cout << ans << endl;
return 0;
}
P8810 [蓝桥杯 2022 国 C] 数组个数 题解的更多相关文章
- P8796 [蓝桥杯 2022 国 AC] 替换字符
题面 给定一个仅含小写英文字母的字符串 \(s\) 和 \(m\) 次操作,每次操作选择一个区间 \([l_i,r_i]\) 将 \(s\) 的该区间中的所有字母 \(x_i\) 全部替换成字母 \( ...
- 2016年蓝桥杯B组C/C++决赛题解
2016年第七届蓝桥杯B组C/C++决赛题解 2016年蓝桥杯B组C/C++决赛题目(不含答案) 1.一步之遥 枚举解方程,或者套模板解线性方程 #include<bits/stdc++.h&g ...
- 2015年蓝桥杯B组C/C++决赛题解
2015年第六届蓝桥杯B组C/C++决赛题解 点击查看2015年第六届蓝桥杯B组C/C++国赛题目(不含答案) 1.积分之迷 三重循环 枚举A,B,C的值,如果满足两个条件:3个A + 7个B ...
- 2018年蓝桥杯B组C/C++决赛题解
2018年第九届蓝桥杯B组C/C++决赛题解 点击查看2018年蓝桥杯B组C/C++决赛题目(不含答案) 1.换零钞 ok 枚举 设x表示1元钱的个数,y表示2元钱的个数,z表示5元钱的个数 x+21 ...
- 2018年蓝桥杯A组C/C++决赛题解
2018年第九届蓝桥杯A组C/C++决赛题解 点击查看视频题解 点击查看2018年蓝桥杯A组C/C++决赛题目(不含答案) 1:三角形面积 画个图,求三角形面积,可以用外接长方形 - 其他多余区域面积 ...
- 第十届蓝桥杯省赛JavaB组个人题解
前言 以下的第十届蓝桥杯Java B组省赛的题目题解只是我个人的题解,提供一些解题思路,仅作参考,如有错误,望大家指出,不甚感激,我会及时更改. 试题 A: 组队 ----- 答案:490 [问题描述 ...
- 2017年蓝桥杯B组C/C++决赛题解
2017年蓝桥杯B组C/C++决赛题目(不含答案) 1.36进制 ok 求36进制,类比二进制转10进制,36^3 + 36^2 + 36^1 + 36^0 2.磁砖样式 ok dfs搜索 我自己写的 ...
- 蓝桥杯 算法训练 ALGO-50 数组查找及替换
算法训练 数组查找及替换 时间限制:1.0s 内存限制:512.0MB 问题描述 给定某整数数组和某一整数b.要求删除数组中可以被b整除的所有元素,同时将该数组各元素按从小到大排序.如果数组元 ...
- Java实现 蓝桥杯 算法训练 删除数组零元素
算法训练 删除数组零元素 时间限制:1.0s 内存限制:512.0MB 提交此题 从键盘读入n个整数放入数组中,编写函数CompactIntegers,删除数组中所有值为0的元素,其后元素向数组首端移 ...
- Java实现 蓝桥杯 算法训练 寻找数组中最大值
算法训练 寻找数组中最大值 时间限制:1.0s 内存限制:512.0MB 提交此题 问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于10 ...
随机推荐
- 2022-02-25:k8s安装zookeeper,yaml如何写?找份北京的golang后端工作,35岁,有人收我吗?
2022-02-25:k8s安装zookeeper,yaml如何写?找份北京的golang后端工作,35岁,有人收我吗? 答案2022-02-25: yaml如下: apiVersion: apps/ ...
- 2021-05-22:假设所有字符都是小写字母, 大字符串是str,arr是去重的单词表, 每个单词都不是空字符串且可以使用任意次。使用arr中的单词有多少种拼接str的方式。 返回方法数。
2021-05-22:假设所有字符都是小写字母, 大字符串是str,arr是去重的单词表, 每个单词都不是空字符串且可以使用任意次.使用arr中的单词有多少种拼接str的方式. 返回方法数. 福大大 ...
- 2021-07-28:最短的桥。在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。返回必须翻转的
2021-07-28:最短的桥.在给定的二维二进制数组 A 中,存在两座岛.(岛是由四面相连的 1 形成的一个最大组.)现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛.返回必须翻转的 ...
- 2021-09-04:加油站。在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost
2021-09-04:加油站.在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升.你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost ...
- 从前后端的角度分析options预检请求
摘要:options预检请求是干嘛的?options请求一定会在post请求之前发送吗?前端或者后端开发需要手动干预这个预检请求吗?不用文档定义堆砌名词,从前后端角度单独分析,大白话带你了解! 本文分 ...
- Charles抓包补充解释
配置 大佬的博客真的很详细很详细,我就不重复造轮子了,第一次直接看大佬的博客就好,这里Python爬取微信小程序(Charles) 补充解释 在这一步疑问很多,大佬说的不是很详细,就由我来补充下吧~ ...
- Elasticsearch与Clickhouse数据存储对比
1 背景 京喜达技术部在社区团购场景下采用JDQ+Flink+Elasticsearch架构来打造实时数据报表.随着业务的发展Elasticsearch开始暴露出一些弊端,不适合大批量的数据查询,高频 ...
- Apache Hudi 1.x 版本重磅功能展望与讨论
Apache Hudi 社区正在对Apache Hudi 1.x版本功能进行讨论,欢迎感兴趣同学参与讨论,PR链接:https://github.com/apache/hudi/pull/8679/f ...
- 大型 3D 互动开发和优化实践
开发背景 得益于"元宇宙"概念在前段时间的爆火,各家公司都推出了使用 3D 场景的活动或频道. 3D 场景相比传统的 2D 页面优点是多一个维度,同屏展示的内容可以更多,能完整的展 ...
- CMU15445 (Fall 2020) 数据库系统 Project#2 - B+ Tree 详解(下篇)
前言 上一篇博客中实现了单线程 B+ 树的查找.插入.删除和迭代操作,这篇博客将完成实验二的剩余任务:并发 B+ 树.实现 B+ 树并发访问最简单的方法就是在整棵树上加一把大锁,但是这样会导致过多线程 ...