这个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 家今天的饭的更多相关文章

  1. 【CSP-S 2019】D2T1 Emiya 家今天的饭

    Description 传送门 Solution 算法1 32pts 爆搜,复杂度\(O((m+1)^n)\) 算法2 84pts 裸的dp,复杂度\(O(n^3m)\) 首先有一个显然的性质要知道: ...

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

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

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

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

  4. CSP2019 Emiya 家今天的饭 题解

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

  5. csp2019 Emiya家今天的饭题解

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

  6. CSP2019 Emiya 家今天的饭

    Description: 有 \(n\) 中烹饪方法和 \(m\) 种食材,要求: 至少做一种菜 所有菜的烹饪方法各不相同 同种食材的菜的数量不能超过总菜数的一半 求做菜的方案数. Solution1 ...

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

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

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

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

  9. [CSP-S2019]Emiya 家今天的饭 题解

    CSP-S2 2019 D2T1 很不错的一题DP,通过这道题学到了很多. 身为一个对DP一窍不通的蒟蒻,在考场上还挣扎了1h来推式子,居然还有几次几乎推出正解,然而最后还是只能打个32分的暴搜滚粗 ...

随机推荐

  1. 同时支持Android 和 ios 投屏到电脑的软件,Support Android and ios screen shrare to PC - 希沃授课助手

    最近学校由粉笔黑板更换了智慧电子黑板,然后发现了一个好玩的软件. 感谢希沃公司的开发: 希沃授课助手,这是一款同时支持Android 和 ios 投屏和远程控制的. 效果很流畅,非常赞

  2. 创建Webpack 4.X项目

    创建基本的webpack4.x项目 运行npm init -y 快速初始化项目 在项目根目录创建src源代码目录和dist产品目录 在 src 目录下创建 index.html 使用 cnpm 安装 ...

  3. windows服务器入门 初始化数据盘

    本人在寒假的时候自行搭建了一个服务器,在此分享一下我的方法.本人服务器的系统为Windows 2012R2 在后面的讲解中中文英文都会有    所以不用在意系统的语言问题 1)第一步  自然就是打开服 ...

  4. Redis内存数据库的基本语法

    Redis: - nosql数据库,非关系型数据库 - 支持5大数据类型 (字符串String,列表list.字典hash,集合set,zset) - 与之相似的有memcache,但memcache ...

  5. 【51nod】1776 路径计数

    [51nod]1776 路径计数 我们先把前两种数给排好,排好之后会有\(a + b + 1\)个空隙可以填数,我们计算有\(k\)个空隙两端都是相同字母的方案数 可以用枚举把第二种数分成几段插进去来 ...

  6. 为什么 Python 中的 True 等于 1

    开始的时候,需要用以下函数来做一个判断,根据返回的值来做一些后续判断处理: def is_success(param): if not param: return False return True ...

  7. logstash grok nginx log

    #cat logstash.conf input { file { path => "/alidata/logs/nginx/appapi.dayutang.cn.access*.lo ...

  8. 理解Python函数和方法

    什么是函数? 函数是抽象出的一组执行特定功能的重复代码,通俗理解,就是对一些重复的工作进行封装和然后直接调用,避免重复造轮子. Python中的函数如何定义? 使用def关键字,结构如下: def 函 ...

  9. python笔记006-文件操作

    1文件操作... 1 1.1打开和关闭文件... 1 1.1.2 open函数... 1 1.2 文件 File对象的属性... 1 1.2.1 属性... 1 1.2.2 方法... 2 1.2.3 ...

  10. vim字符匹配

    按 : 这个符号进入命令模式后,可以对文本信息进行替换.删除等操作.