CSP-S2 2019 D2T1

很不错的一题DP,通过这道题学到了很多。

身为一个对DP一窍不通的蒟蒻,在考场上还挣扎了1h来推式子,居然还有几次几乎推出正解,然而最后还是只能打个32分的暴搜滚粗


题意分析

给出一个矩阵,要求每行只能选一个节点,每列选的节点不能超过所有选的节点的一半,不能不选,给出每个节点的选择方案数,求总方案数

思路分析

可以看出,维护每列已选的节点复杂度太大,不太可行;因此很容易想到,先不考虑每列不超过一半的这个限制,求出总方案数,然后再减去考虑这个限制后不合法的方案数。现在问题就变成,求任意列选的节点超过所有选的节点的一半的方案数之和。

显然,在一个方案中,只可能有一列的节点超过所有选的节点的一半。因此可以想到枚举这个超过限制的列,然后对于这个列进行DP求解。

具体实现

设$f_{i,j,k}$表示前$i$行选$j$个节点,当前枚举到的列选$k$个节点的方案数。对于每个列,复杂度为$O(n^3)$,总的复杂度为$O(mn^3)$,可以得到84分的高分。

想得到满分还需要进一步优化。考虑将某两个状态合并。观察状态,实际上我们想知道的只是$j,k$的大小关系,对于具体的值并不关心,考虑将它们合并到一维。

考虑我们需要的限制条件$k>\left \lfloor \frac{j}{2} \right \rfloor$,变形一下可以得到$2k+n-j>n$。观察这个式子,可以发现,$n-j$就是这$n$行里没有选的行数。然后一个奇妙的想法就出来了,对于每个节点,选它时当做该列选了两次,而对于某一行不选时,当做所有列选了一次,最终要找的就是当前列被选超过$n$次的方案。这样就成功地优化掉了第二维。

给一下状态转移方程:

f[j][k]=(f[j][k]+f[j-1][k]*(cnt[j]-w[j][i]))%P;//不选当前列
f[j][k+1]=(f[j][k+1]+f[j-1][k])%P;//不选当前行
f[j][k+2]=(f[j][k+2]+f[j-1][k]*w[j][i])%P;//选当前行当前列对应的节点

注意取模时出现负数的情况,记得开long long。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=200,M=3000,P=998244353;//FFT(雾
int n,m;
ll ans=1;
ll cnt[N],w[N][M],f[N][M];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
scanf("%lld",&w[i][j]),cnt[i]=(cnt[i]+w[i][j])%P;
ans=(ans*(cnt[i]+1))%P;//计算全部答案
}
ans=(ans+P-1)%P;//减去全部不选的情况
for(int i=1;i<=m;i++)
{
memset(f,0,sizeof(f));
f[0][0]=1;//DP初值
for(int j=1;j<=n;j++)
for(int k=0;k<=2*(j-1);k++)
{
f[j][k]=(f[j][k]+f[j-1][k]*(cnt[j]-w[j][i]))%P;
f[j][k+1]=(f[j][k+1]+f[j-1][k])%P;
f[j][k+2]=(f[j][k+2]+f[j-1][k]*w[j][i])%P;
}
for(int j=n+1;j<=2*n;j++)
ans=(ans+P-f[n][j])%P;//减去当前枚举到的不合法方案
}
printf("%lld",ans);
return 0;
}

[CSP-S2019]Emiya 家今天的饭 题解的更多相关文章

  1. 洛谷P5664 Emiya 家今天的饭 题解 动态规划

    首先来看一道题题: 安娜写宋词 题目背景 洛谷P5664 Emiya 家今天的饭[民间数据] 的简化版本. 题目描述 安娜准备去参加宋词大赛,她一共掌握 \(n\) 个 词牌名 ,并且她的宋词总共有 ...

  2. csp2019 Emiya家今天的饭题解

    qwq 由于窝太菜了,实在是不会,所以在题解的帮助下过掉了这道题. 写此博客来整理一下思路 正文 传送 简化一下题意:现在有\(n\)行\(m\)列数,选\(k\)个数的合法方案需满足: 1.一行最多 ...

  3. CSP2019 Emiya 家今天的饭 题解

    这题在考场上只会O(n^3 m),拿了84分.. 先讲84分,考虑容斥,用总方案减去不合法方案,也就是枚举每一种食材,求用它做超过\(\lfloor \frac{k}{2} \rfloor\) 道菜的 ...

  4. 洛谷P5664 Emiya 家今天的饭 问题分析

    首先来看一道我编的题: 安娜写宋词 题目背景 洛谷P5664 Emiya 家今天的饭[民间数据] 的简化版本. 题目描述 安娜准备去参加宋词大赛,她一共掌握 \(n\) 个 词牌名 ,并且她的宋词总共 ...

  5. Emiya家今天的饭 NOIP2019 (CSP?) 类DP好题 luoguP5664

    luogu题目传送门! 首先,硬求可行方案数并不现实,因为不好求(去年考场就这么挂的,虽然那时候比现在更蒟). 在硬搞可行方案数不行之后,对题目要求的目标进行转换: 可行方案数 = 总方案数 - 不合 ...

  6. 【CSP-S 2019】【洛谷P5664】Emiya 家今天的饭【dp】

    题目 题目链接:https://www.luogu.org/problem/P5664 Emiya 是个擅长做菜的高中生,他共掌握 \(n\) 种烹饪方法,且会使用 \(m\) 种主要食材做菜.为了方 ...

  7. 【NOIP/CSP2019】D2T1 Emiya 家今天的饭

    这个D2T1有点难度啊 原题: 花了我一下午的时间,作为D2T1的确反常 条件很奇怪,感觉不太直观,于是看数据范围先写了个暴力 写暴力的时候我就注意到了之前没有仔细想过的点,烹饪方式必须不同 虽然a很 ...

  8. P5664 Emiya 家今天的饭

    题面 link 前言 去年把我做自闭的一道题,看了一眼题面,发现只有 t1 有点思路,结果写到一半发现自己读错题了,又只能花时间来重构,结果后面的暴力一点都没写(主要是自己当时不会) 然后,这道题还因 ...

  9. 洛谷 P5664 [CSP-S2019] Emiya 家今天的饭

    链接: P5664 题意: 给出一个 \(n*m\) 的矩阵 \(a\),选 \(k\) 个格子(\(1\leq k\leq n\)),每行最多选一个,每列最多选\(⌊\dfrac k2⌋\) 个,同 ...

随机推荐

  1. PHP rmdir() 函数

    定义和用法 rmdir() 函数删除空的目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 rmdir(dir,context) 参数 描述 dir 必需.规定要删除的目录. ...

  2. luogu3706 [SDOI2017]硬币游戏

    LINK:硬币游戏 对于40分的暴力 构造出AC自动机 列出转移矩阵 暴力高消.右转上一篇文章. 对于100分 我们不难想到这个矩阵过大 且没有用的节点很多我们最后只要n个节点的答案 其他节点的答案可 ...

  3. react-ts模板/脚手架

    react-ts-template 脚手架 使用 npm i -g maple-react-cli maple-react-cli init 选择模板 'react-ts-template' 输入自定 ...

  4. 从入门到熟悉HTTPS的9个问题

    原文:bestswifter   https://juejin.im/post/58c5268a61ff4b005d99652a Q1: 什么是 HTTPS? BS: HTTPS 是安全的 HTTP ...

  5. static关键字设计原理

    语法只是表象,原理才是关键!!! 灵魂static关键字 Java规定:方法只能由对象来调用. 换句话来说,在面向对象的思维下,方法与对象存在一种强耦合. 方法在没有对象的情况下无法调用,于是上帝派来 ...

  6. 解决IIS发布时CS0016未能写入输出文件错误

    今天遇到一个将asp.net项目部署到IIS后访问的时候报的一个错误: 在网上查询了相关资料后,解决方法如下: 找到C:\Windows\下的temp文件,右键属性>安全>编辑,给其中II ...

  7. 当asp.net core偶遇docker一(模型验证和Rabbitmq 二)

    上一篇我们说到构建了一个Rabbitmq容器 现在我们说说如何在一个悄悄传输消息到队列 我们现在设计一个Rabbitmq发送消息部分的模块 先设计一个远程发送的接口 public interface ...

  8. day23:单继承&多继承&菱形继承&__init__魔术方法

    1.单继承 1.1 关于继承的一些基本概念 1.2 子类可以调用父类的公有成员 1.3 子类无法调用父类的私有成员 1.4 子类可以改写父类的方法 2.多继承 2.1 多继承的基本语法 2.2 sup ...

  9. Android 进度条(ProgressBar)和拖动条(Seekbar)补充“自定义组件”(总结)

    这周结束了,我也码了一周的字,感觉还是很有种脚踏实地的感觉的,有时间就可以看看自己的总结再查漏补缺,一步一个脚印,做出自己最理想的项目. 今天我们讲两点: 1.ProgressBar: 其实前面也稍微 ...

  10. python5.2文件写入

    fh=open(r"C:\55.txt","w")#文件编写新的文字,替代原有的文字!w:writedata = "努力让生活更美好!"fh ...