2019 Multi-University Training Contest 1 - 1001 - Blank - dp
http://acm.hdu.edu.cn/showproblem.php?pid=6578
不会做,看题解。
设dp[i][j][k][l]表示4种颜色出现的最后的位置分别是i,j,k,l的方法数,保证i>=j>=k>=l。其实不取=号,因为同一个位置不能放两个元素,除了开始的若干个比如dp[1][0][0][0]=4。
合法的转移叠加:
比如
刷新的颜色是i:dp[i+1][j][k][l]+=dp[i][j][k][l]
刷新的颜色是j:dp[i+1][i][k][l]+=dp[i][j][k][l]
刷新的颜色是k:dp[i+1][i][j][l]+=dp[i][j][k][l]
刷新的颜色是l:dp[i+1][i][j][k]+=dp[i][j][k][l]
假如从dp[i][j][k][l]转移到上述状态会导致新状态不满足约束则不进行这次转移,就太麻烦了。
由于是dp,其实只要遇到约束区间的右端点R的时候再考虑约束就可以了。
考虑四个数其实是[l,k,j,i],i肯定就是R,要是l>=L则有恰好4种颜色,否则要是k>=L则恰好3种颜色,否则要是j>=L则恰好2种颜色,否则只有1种颜色。
对每次转移后新状态的i维度必定是i+1,对i维度进行滚动节省空间。复杂度是精确的O(n4+mn3),据说很多队觉得过不了。
还卡memset???15组数据还卡memset?
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int x = 0;
char c = 0;
while(c < '0' || c > '9')
c = getchar();
while(c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x;
}
inline void _write(int x) {
if(x > 9)
_write(x / 10);
putchar(x % 10 + '0');
}
inline void write(int x) {
_write(x);
putchar('\n');
}
struct Condition {
int l, r, x;
bool operator<(const Condition &c)const {
return r < c.r;
}
} con[105];
const int mod = 998244353;
int n, m, dp[2][105][105][105], ctop;
inline void clear0(int n) {
for(int j = 0; j <= n; ++j) {
for(int k = 0; k <= j; ++k) {
for(int l = 0; l <= k; ++l) {
dp[n & 1][j][k][l] = 0;
}
}
}
}
inline void clear1(int i, int L) {
//清除==1种的
for(int j = L - 1 ; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
}
inline void clear2(int i, int L) {
//清除==2种的
for(int j = i ; j >= L; --j) {
for(int k = L - 1; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
}
inline void clear3(int i, int L) {
//清除==3种的
for(int j = i ; j >= L ; --j) {
for(int k = j ; k >= L; --k) {
for(int l = L - 1; l >= 0; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
}
inline void clear4(int i, int L) {
//清除==4种的
for(int j = i ; j >= L ; --j) {
for(int k = j ; k >= L ; --k) {
for(int l = k ; l >= L; --l) {
dp[i & 1][j][k][l] = 0;
}
}
}
}
inline void update1(int i) {
if(ctop > m || i < con[ctop].r)
return;
while(ctop <= m && i == con[ctop].r) {
//printf("cons %d\n", ctop);
int L = con[ctop].l, x = con[ctop].x;
++ctop;
if(x == 1) {
clear2(i, L);
clear3(i, L);
clear4(i, L);
} else if(x == 2) {
clear1(i, L);
clear3(i, L);
clear4(i, L);
} else if(x == 3) {
clear1(i, L);
clear2(i, L);
clear4(i, L);
} else {
clear1(i, L);
clear2(i, L);
clear3(i, L);
}
}
}
inline void update2(int i, int j, int k, int l) {
dp[(i + 1) & 1][j][k][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][j][k][l] >= mod)
dp[(i + 1) & 1][j][k][l] -= mod;
dp[(i + 1) & 1][i][k][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][k][l] >= mod)
dp[(i + 1) & 1][i][k][l] -= mod;
dp[(i + 1) & 1][i][j][l] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][j][l] >= mod)
dp[(i + 1) & 1][i][j][l] -= mod;
dp[(i + 1) & 1][i][j][k] += dp[i & 1][j][k][l];
if(dp[(i + 1) & 1][i][j][k] >= mod)
dp[(i + 1) & 1][i][j][k] -= mod;
}
int solve() {
ctop = 1;
memset(dp[1], 0, sizeof(dp[1]));
dp[1][0][0][0] = 4;
update1(1);
for(int i = 1; i <= n - 1; ++i) {
//printf("i=%d\n", i);
clear0(i + 1);
for(int j = i; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
if(k == j && k)
continue;
for(int l = k ; l >= 0; --l) {
if(l == k && l)
continue;
update2(i, j, k, l);
}
}
}
update1(i + 1);
for(int j = i; j >= 0; --j) {
for(int k = j; k >= 0; --k) {
if(k == j && k)
continue;
for(int l = k ; l >= 0; --l) {
if(l == k && l)
continue;
//printf("dp[%d][%d][%d][%d]=%d\n", i + 1, j, k, l, dp[(i + 1) & 1][j][k][l]);
}
}
}
//printf("\n");
}
int ans = 0;
for(int j = n - 1; j >= 0; --j) {
for(int k = j ; k >= 0; --k) {
for(int l = k ; l >= 0; --l) {
ans += dp[n & 1][j][k][l];
if(ans >= mod)
ans -= mod;
}
}
}
return ans;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int T = read();
while(T--) {
n = read(), m = read();
for(int i = 1; i <= m; ++i) {
con[i].l = read(), con[i].r = read(), con[i].x = read();
}
sort(con + 1, con + 1 + m);
write(solve());
}
return 0;
}
2019 Multi-University Training Contest 1 - 1001 - Blank - dp的更多相关文章
- HDU 6362.oval-and-rectangle-数学期望、微积分 (2018 Multi-University Training Contest 6 1001)
2018 Multi-University Training Contest 6 6362.oval-and-rectangle 题意就是椭圆里画内接矩形,问你矩形周长的期望. 比赛的时候推了公式,但 ...
- HDU 6319.Problem A. Ascending Rating-经典滑窗问题求最大值以及COUNT-单调队列 (2018 Multi-University Training Contest 3 1001)
2018 Multi-University Training Contest 3 6319.Problem A. Ascending Rating 题意就是给你长度为k的数列,如果数列长度k<n ...
- HDU 6298.Maximum Multiple-数学思维题(脑子是个好东西,可惜我没有) (2018 Multi-University Training Contest 1 1001)
暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.M ...
- 2019 Multi-University Training Contest 1 A.Blank(dp)
题意:现在要你构造一个只有{0,1,2,3} 长度为n且有m个限制条件的序列 问你方案数 思路:dp[i][j][k][now]分别表示四个数最后出现的位置 最后可以滚动数组 优化一下空间 ps:我的 ...
- 2015 Multi-University Training Contest 1 - 1001 OO’s Sequence
OO’s Sequence Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5288 Mean: 给定一个数列,让你求所有区间上满足 ...
- 2015 Multi-University Training Contest 3 1001 Magician
Magician Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5316 Mean: n个数,2种操作,1是单点更新,2是询问区间 ...
- 2015 Multi-University Training Contest 4 1001 Olympiad
代码: #include<cstdio> #include<cstring> #include<set> using namespace std; int vis[ ...
- 2019 Nowcoder Multi-University Training Contest 4 E Explorer
线段树分治. 把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边. 注意把左右端点的关系. #include <bits/stdc++.h> ; int X[ ...
- 2019 Nowcoder Multi-University Training Contest 1 H-XOR
由于每个元素贡献是线性的,那么等价于求每个元素出现在多少个异或和为$0$的子集内.因为是任意元素可以去异或,那么自然想到线性基.先对整个集合A求一遍线性基,设为$R$,假设$R$中元素个数为$r$,那 ...
随机推荐
- jquery 对于新插入的节点 的操作绑定(点击事件,each等)
因为最近项目遇到这个问题,下面给大家带来一篇Jquery对新插入的节点 获取并对这个节点绑定事件失效的解决方法.我觉得挺不错的,大家也可以参考一下: 对于绑定事件来讲: 方法一:使用liv ...
- Linux学习-基于CentOS7的LAMP环境实现多虚拟主机
一.实验环境 系统:CentOS7.6 主机:两台(一台也可以),一台实现apache+php-fpm (192.168.214.17),一台实现mysql服务器 (192.168.214.27) 软 ...
- 寻找的常用webstorm快捷键
1. 必备快捷键 Ctrl+/:注释当前行 Ctrl+Shift+/:当前位置插入注释 Ctrl+Alt+/:块注释,并Focus到首行,写注释说明用的 Ctrl+Shift+A:选择当前标签前后,修 ...
- JS循环结构
什么是循环结构? 反复一遍又一遍做着相同(相似)的事情 循环结构的两大要素? 循环条件:什么时候开始,什么时候结束 循环操作:循环体,循环过程中 做了什么 一.while语句 while语句 属于前测 ...
- 【bzoj3566】 [SHOI2014]概率充电器
*题目描述: 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器: “采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可 ...
- echarts曲线图
drawLeftLine(){ let drawLine = echarts.init(document.getElementById('data-left-middle-table-wrap')); ...
- Beauty Values
Beauty Values 题意:给$n$个数, 定义它的Beauty Values为所有连续子区间的(区间长度*区间内不同数字的数目)求和 求Beauty Values A[i]数组表示数字i最近一 ...
- AtomicReference 源码分析
AtomicReference AtomicReference 能解决什么问题?什么时候使用 AtomicReference? 1)AtomicReference 可以原子更新引用对象. 2)comp ...
- EDM营销必知:电子邮件打开和点击的几组数据
在EDM营销中,了解一下电子邮件何时被打开和点击很重要.这有助于我们在合适的时间发送邮件出去,从而带来最大化的效果. 1.邮件打开的最高峰在早上8点至9点之间,其次是下午三点到四点.因此,在这个时间发 ...
- 浅释Functor、Applicative与Monad
引言 转入Scala一段时间以来,理解Functor.Applicative和Monad等概念,一直是我感到头疼的部分.虽然读过<Functors, Applicatives, And Mona ...