这个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了

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. #define LL long long
  8. const int mo=;
  9. int rd(){int z=,mk=; char ch=getchar();
  10. while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
  11. while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
  12. return z*mk;
  13. }
  14. int n,m,a[][];
  15. LL ans=;
  16. int cnt[];
  17. LL s[];
  18. LL f7[][][];
  19. LL f[][];
  20. bool chck(int x){
  21. if(!x) return false;
  22. //注意x=0时必须特判,因为此时cnt也全是0,下面条件不会成立
  23. for(int i=;i<=m;++i)if(cnt[i]>x/) return false;
  24. return true;
  25. }
  26. void dfs(int x,int y,LL z){
  27. if(x==n+){
  28. if(chck(y)) ans=(ans+z)%mo;
  29. return ;
  30. }
  31. dfs(x+,y,z);
  32. for(int i=;i<=m;++i)if(a[x][i]){
  33. ++cnt[i];
  34. dfs(x+,y+,z*a[x][i]%mo);
  35. --cnt[i];
  36. }
  37. }
  38. LL gan(int x){
  39. memset(f7,,sizeof(f7));
  40. f7[][][]=;
  41. for(int i=;i<=n;++i)for(int j=;j<=i;++j)for(int k=;k<=j;++k){
  42. f7[i][j][k]=f7[i-][j][k];
  43. if(j && k) f7[i][j][k]=(f7[i][j][k]+f7[i-][j-][k-]*a[i][x]%mo)%mo;
  44. if(j) f7[i][j][k]=(f7[i][j][k]+f7[i-][j-][k]*(s[i]-a[i][x])%mo)%mo;
  45. }
  46. LL bwl=;
  47. for(int i=;i<=n;++i)for(int j=i/+;j<=i;++j) bwl=(bwl+f7[n][i][j])%mo;
  48. return bwl;
  49. }
  50. LL ganisok(int x){
  51. memset(f,,sizeof(f));
  52. f[][n]=;
  53. for(int i=;i<=n;++i)for(int j=;j<=n+n;++j){
  54. f[i][j]=f[i-][j];
  55. if(j) f[i][j]=(f[i][j]+f[i-][j-]*a[i][x]%mo)%mo;
  56. if(j<n+n) f[i][j]=(f[i][j]+f[i-][j+]*(s[i]-a[i][x]%mo))%mo;
  57. }
  58. LL bwl=;
  59. for(int i=n+;i<=n+n;++i) bwl=(bwl+f[n][i])%mo;
  60. return bwl;
  61. }
  62. int main(){
  63. //freopen("ddd.in","r",stdin);
  64. cin>>n>>m;
  65. for(int i=;i<=n;++i)for(int j=;j<=m;++j) a[i][j]=rd();
  66. if(n<= && m<=){
  67. dfs(,,);
  68. cout<<ans<<endl;
  69. }
  70. else if(n<= && m<=){
  71. for(int i=;i<=n;++i){
  72. s[i]=;
  73. for(int j=;j<=m;++j) s[i]=(s[i]+a[i][j])%mo;
  74. }
  75. LL bwl=;
  76. for(int i=;i<=n;++i) bwl=bwl*(s[i]+)%mo;
  77. bwl-=;
  78. for(int i=;i<=m;++i) bwl=(bwl-gan(i))%mo;
  79. cout<<(bwl%mo+mo)%mo<<endl;
  80. }
  81. else{
  82. for(int i=;i<=n;++i){
  83. s[i]=;
  84. for(int j=;j<=m;++j) s[i]=(s[i]+a[i][j])%mo;
  85. }
  86. LL bwl=;
  87. for(int i=;i<=n;++i) bwl=bwl*(s[i]+)%mo;
  88. bwl-=;
  89. for(int i=;i<=m;++i) bwl=(bwl-ganisok(i))%mo;
  90. cout<<(bwl%mo+mo)%mo<<endl;
  91. }
  92. return ;
  93. }

【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. sed练习,一些sed常用方法

    1.复制/etc/rc.d/rc.local 文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#. sed -ri 's/^ +/#/g'  rc.loc ...

  2. 【miscellaneous】GStreamer下的音视频播放

    Gst-launch命令: gst-launch filesrc location=*.* ! demux name=demux demux.video_00 ! queue ! decoder ! ...

  3. [转帖]8个优秀Docker容器监控工具,收藏了

    8个优秀Docker容器监控工具,收藏了 Docker是目前使用最广泛的容器之一,但它并不总是像物理硬件一样可见.而使用docker容器监控工具有助于消除这种透明度的缺失.以下介绍8种优秀Docker ...

  4. ASP.NET请求过程-基本过程

    客户端发送请求到达服务器 输入域名->DNS解析->指定IP 服务器(如果网页直接输入IP地址则直接到服务器)->请求到达服务器->HTTP.SYS接受HTTP请求->转 ...

  5. NoSQL数据库一Redis基本使用

    基本操作 参考教程:https://www.yiibai.com/redis/Redis 是 Key-Value 内存数据库,操作是通过各种指令进行的,比如 SET 指令可以设置键值对,而 GET 指 ...

  6. (十)EL表达式和JSTL标签快速入门

    目录 什么是 el 表达式 示例:使用EL表达式获取pageContext .request.session.application域中的数据: 示例:使用EL表达式获取Bean属性 获取当前WEB应 ...

  7. Django中常用的那些模块路径

    Django中常用的那些模块路径 from django.shortcuts import HttpResponse, render, redirect from django import temp ...

  8. vsftp多个用户公享同一个文件,但是权限不同

    如标题:vsftp多个用户公享同一个文件,但是权限不同.如何做到呢.首先创建多个用户,并且指定同一个目录

  9. Codefroces 1245 F. Daniel and Spring Cleaning

    传送门 考虑简单的容斥 设 $F(n,m)$ 表示 $a \in [1,n] , b \in [1,m]$ 的满足 $a+b=a \text{ xor } b$ 的数对的数量 那么答案即为 $F(r, ...

  10. C# DateTime Subtract

    DateTime start = DateTime.Now.AddDays(-20); DateTime end = DateTime.Now; TimeSpan ts = end.Subtract( ...