【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分的暴搜滚粗 ...
随机推荐
- todolist形式的搜索框,分开组件写的,点击上下键时,框内显示当前选中的内容
### 首先 安装react 脚手架 cnpm install create-react-app -g //只需要在电脑上安装一次就好了,以后不用再下载了 ### 创建项目 crea ...
- 图形学入门(3)——区域填充算法(region filling)
继续图形学之旅,我们已经解决了如何画线和画圆的问题,接下来要解决的是,如何往一个区域内填充颜色?对一个像素填充颜色只需调用SetPixel之类的函数就行了,所以这个问题其实就是:如何找到一个区域内的所 ...
- 最新 游族网络java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.游族网络等10家互联网公司的校招Offer,因为某些自身原因最终选择了游族网络.6.7月主要是做系统复习.项目复盘.Leet ...
- Spring 使用日志
1. spring boot项目默认使用什么技术处理日志? 实例代码 log.debug("===============================用户信息:", user) ...
- Shiro加盐加密
接本人的上篇文章<Shiro认证.角色.权限>,这篇文章我们来学习shiro的加盐加密实现 自定义Realm: package com.czhappy.realm; import org. ...
- jira使用一:如何给项目分组、sprint并行、禁止发送消息给atlassian
问题一:如何设置多个sprint并行? 问题二: 如何分组显示 设置泳道,并快速过滤 问题3:添加所属产品? 管理员登录Jira后台设置-问题-自定义字段找到:所属产品,进入 配置 界面在配置界面中, ...
- Servlet 响应及请求信息
// 文件路径 D:\ApacheServer\web_java\HelloWorld\src\com\test\TestServletRequestrResponse.java package co ...
- sql server 2012 链接服务器不能链接sql server 2000的解决方案 ,
本数据源来自 https://www.kafan.cn/edu/922556.html 目的为了备忘 把原来的sql server 2005直接装成了2012,然后在建立链接服务器链接一台sql s ...
- insert 一条数据 然后拿出这条数据在数据库中生成的ID
[insert 一条数据 然后拿出这条数据在数据库中生成的ID] <insert id="insert" parameterType="management&quo ...
- 习题一初步理解时间复杂度大O表示法案例
1.如果 a+b+c=1000,且 a^2+b^2=c^2(a,b,c 为自然数),如何求出所有a.b.c可能的组合? 如上:a+b+c=1000, a平方+b平方=c平方 求出所有abc可能的组合 ...