【NOIP/CSP2019】D2T1 Emiya 家今天的饭
这个D2T1有点难度啊
原题:


花了我一下午的时间,作为D2T1的确反常
条件很奇怪,感觉不太直观,于是看数据范围先写了个暴力
写暴力的时候我就注意到了之前没有仔细想过的点,烹饪方式必须不同
虽然a很大,但是n只有100,即总菜数比较小
而且虽然m和a都很大,但是一种方法只能做一道菜,即选一种食材
所以搜索枚举每种方法选哪种食材,最后检查方案是否满足条件
这样可以拿到32分
需要注意到一点很关键的性质
不管什么方案,最多只有一个食材能超过n/2,看到n/2要敏感
那么如果无视n/2的限制,直接dp就vans了,接下来只需要去掉不合法的方案
枚举哪一种食材超过n/2,可以发现此时食材只有两种,枚举到的食材和其他的食材
需要表达的状态数大大减少
设计状态,f[i][j][k]表示直到第i种方式,总共选了j道菜,其中k道菜用当前枚举食材
这样可以拿到82分
然后就不会了233
这个递推又没有决策,咋优化啊
本着单个题目思考时间不能过长的原则,观摩了python96的题解:
https://blog.csdn.net/weixin_37517391/article/details/103110646
立刻点化233
确实不太好想,果然适时看题解效率更高
我们记录状态的时候不必记录两类食材的数量,只需记录二者差值即可
只要差值相同,不同的数量对于合法性的判断都是等价的
那么以前的3维dp就优化到2维,可以ac了
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
const int mo=;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
int n,m,a[][];
LL ans=;
int cnt[];
LL s[];
LL f7[][][];
LL f[][];
bool chck(int x){
if(!x) return false;
//注意x=0时必须特判,因为此时cnt也全是0,下面条件不会成立
for(int i=;i<=m;++i)if(cnt[i]>x/) return false;
return true;
}
void dfs(int x,int y,LL z){
if(x==n+){
if(chck(y)) ans=(ans+z)%mo;
return ;
}
dfs(x+,y,z);
for(int i=;i<=m;++i)if(a[x][i]){
++cnt[i];
dfs(x+,y+,z*a[x][i]%mo);
--cnt[i];
}
}
LL gan(int x){
memset(f7,,sizeof(f7));
f7[][][]=;
for(int i=;i<=n;++i)for(int j=;j<=i;++j)for(int k=;k<=j;++k){
f7[i][j][k]=f7[i-][j][k];
if(j && k) f7[i][j][k]=(f7[i][j][k]+f7[i-][j-][k-]*a[i][x]%mo)%mo;
if(j) f7[i][j][k]=(f7[i][j][k]+f7[i-][j-][k]*(s[i]-a[i][x])%mo)%mo;
}
LL bwl=;
for(int i=;i<=n;++i)for(int j=i/+;j<=i;++j) bwl=(bwl+f7[n][i][j])%mo;
return bwl;
}
LL ganisok(int x){
memset(f,,sizeof(f));
f[][n]=;
for(int i=;i<=n;++i)for(int j=;j<=n+n;++j){
f[i][j]=f[i-][j];
if(j) f[i][j]=(f[i][j]+f[i-][j-]*a[i][x]%mo)%mo;
if(j<n+n) f[i][j]=(f[i][j]+f[i-][j+]*(s[i]-a[i][x]%mo))%mo;
}
LL bwl=;
for(int i=n+;i<=n+n;++i) bwl=(bwl+f[n][i])%mo;
return bwl;
}
int main(){
//freopen("ddd.in","r",stdin);
cin>>n>>m;
for(int i=;i<=n;++i)for(int j=;j<=m;++j) a[i][j]=rd();
if(n<= && m<=){
dfs(,,);
cout<<ans<<endl;
}
else if(n<= && m<=){
for(int i=;i<=n;++i){
s[i]=;
for(int j=;j<=m;++j) s[i]=(s[i]+a[i][j])%mo;
}
LL bwl=;
for(int i=;i<=n;++i) bwl=bwl*(s[i]+)%mo;
bwl-=;
for(int i=;i<=m;++i) bwl=(bwl-gan(i))%mo;
cout<<(bwl%mo+mo)%mo<<endl;
}
else{
for(int i=;i<=n;++i){
s[i]=;
for(int j=;j<=m;++j) s[i]=(s[i]+a[i][j])%mo;
}
LL bwl=;
for(int i=;i<=n;++i) bwl=bwl*(s[i]+)%mo;
bwl-=;
for(int i=;i<=m;++i) bwl=(bwl-ganisok(i))%mo;
cout<<(bwl%mo+mo)%mo<<endl;
}
return ;
}
【NOIP/CSP2019】D2T1 Emiya 家今天的饭的更多相关文章
- 【CSP-S 2019】D2T1 Emiya 家今天的饭
Description 传送门 Solution 算法1 32pts 爆搜,复杂度\(O((m+1)^n)\) 算法2 84pts 裸的dp,复杂度\(O(n^3m)\) 首先有一个显然的性质要知道: ...
- 洛谷P5664 Emiya 家今天的饭 问题分析
首先来看一道我编的题: 安娜写宋词 题目背景 洛谷P5664 Emiya 家今天的饭[民间数据] 的简化版本. 题目描述 安娜准备去参加宋词大赛,她一共掌握 \(n\) 个 词牌名 ,并且她的宋词总共 ...
- 洛谷P5664 Emiya 家今天的饭 题解 动态规划
首先来看一道题题: 安娜写宋词 题目背景 洛谷P5664 Emiya 家今天的饭[民间数据] 的简化版本. 题目描述 安娜准备去参加宋词大赛,她一共掌握 \(n\) 个 词牌名 ,并且她的宋词总共有 ...
- CSP2019 Emiya 家今天的饭 题解
这题在考场上只会O(n^3 m),拿了84分.. 先讲84分,考虑容斥,用总方案减去不合法方案,也就是枚举每一种食材,求用它做超过\(\lfloor \frac{k}{2} \rfloor\) 道菜的 ...
- csp2019 Emiya家今天的饭题解
qwq 由于窝太菜了,实在是不会,所以在题解的帮助下过掉了这道题. 写此博客来整理一下思路 正文 传送 简化一下题意:现在有\(n\)行\(m\)列数,选\(k\)个数的合法方案需满足: 1.一行最多 ...
- CSP2019 Emiya 家今天的饭
Description: 有 \(n\) 中烹饪方法和 \(m\) 种食材,要求: 至少做一种菜 所有菜的烹饪方法各不相同 同种食材的菜的数量不能超过总菜数的一半 求做菜的方案数. Solution1 ...
- 【CSP-S 2019】【洛谷P5664】Emiya 家今天的饭【dp】
题目 题目链接:https://www.luogu.org/problem/P5664 Emiya 是个擅长做菜的高中生,他共掌握 \(n\) 种烹饪方法,且会使用 \(m\) 种主要食材做菜.为了方 ...
- Emiya家今天的饭 NOIP2019 (CSP?) 类DP好题 luoguP5664
luogu题目传送门! 首先,硬求可行方案数并不现实,因为不好求(去年考场就这么挂的,虽然那时候比现在更蒟). 在硬搞可行方案数不行之后,对题目要求的目标进行转换: 可行方案数 = 总方案数 - 不合 ...
- [CSP-S2019]Emiya 家今天的饭 题解
CSP-S2 2019 D2T1 很不错的一题DP,通过这道题学到了很多. 身为一个对DP一窍不通的蒟蒻,在考场上还挣扎了1h来推式子,居然还有几次几乎推出正解,然而最后还是只能打个32分的暴搜滚粗 ...
随机推荐
- 利用socket编程在ESP32上搭建一个TCP客户端
通过之前http://www.cnblogs.com/noticeable/p/7636582.html中对socket的编程,已经可以知道如何通过socket编程搭建服务器和客户端了,现在,就在ES ...
- Object.defineProperty()方法学习笔记
这是js中一个非常重要的方法,ES6中某些方法的实现依赖于它,VUE通过它实现双向绑定 此方法会直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象 参数 Object.def ...
- 常见问题:计算机网络/运输层/TCP
TCP 面向连接,全双工,点对点. TCP头格式 TCP包没有IP地址,IP地址在网络层的IP协议中,TCP包包括源端口号,目标端口号 一个TCP连接需要四个元祖表明是同一连接(src_ip,src_ ...
- OpenGL学习笔记 之三 (简单示例 太阳月亮地球)
#include<glut.h> // 太阳.地球和月亮 // 假设每个月都是30天 // 一年12个月,共是360天 ;//day的变化:从0到359 void myDisplay(vo ...
- 移动架构-手写ButterKnife框架
ButterKnife在实际开发中有着大量运用,其强大的view绑定和click事件处理,使得开发效率大大提高,同时增加了代码的阅读性又不影响其执行效率 注解的分类 注解主要有两种分类,一个是运行时, ...
- ES6 中 let 和 const 总结
目录 let const 1. let要好好用 1. 基本用法 2. let声明的变量不存在变量提升 3. TDZ(temporal dead zone)暂时性死区 4. 不允许重复声明 2. 块级作 ...
- openstack环境-解决windows虚机重启后比当前时间晚8小时问题
背景: 生产环境下,发现windows虚机每次重启,时间都会倒退到虚机的格林威治时间(+8小时才是北京时间),也就是比当前时间晚8小时.测试发现,windows虚机所用的镜像,缺少了一个os_type ...
- 联想U310 安装系统后无法识别机械硬盘处理
过程: 原30G的固态更换成250G的 mSATA固态,去掉机械硬盘,开始在固态里安装系统, 系统用PE登录,安装正版Win7 64B 专业版, 安装结束,接上机械硬盘, *PE下,可以正常识别2块硬 ...
- 北京大学1001ACM——高精度类型题总结
题目描述: ExponentiationTime Limit: 500MS Memory Limit: 10000KTotal Submissions: 80517 Accepted: 190 ...
- D盘Program Files 文件夹里文件不显示,没隐藏。怎么才能显示出来?
D盘里有两个一模一样的Program Files 文件夹,文件夹里文件不显示,没隐藏.怎么才能显示出来?新买不久的电脑,win8.1系统 点击开始---运行---输入“cmd”(没有引号)---在弹出 ...