题目传送门

题意

这个题的意思就是说,每一行只能选一个(你可以选你也可以不选,但是你只能选一个),你选出来的种类数nnn,其中n/2n/2n/2不能是同一列的东西,请问你有多少种选法。

思路

这道题,其实容斥的思想非常简单,主要还是dp来计数比较复杂。
容斥的思想其实就是正难则反,我记录全部的合法数量,然后减去我们的不合法数量就可以。
我们的合法数量很好计算,我们计算每一行的前缀和sum[i]sum[i]sum[i]那么一共有sum[i]+1sum[i]+1sum[i]+1种选法,(不选的情况),然后根据乘法原理,求可以求出全部的情况了,值得注意的是,全部的情况要减去一种,代表的是什么也不选的一个情况
那么我们现在来计算一下不满足题意的情况,首先通过分析,我们可以轻松的得出,这个一定是一个子状态的问题,而且没有后效性,也就是后面的选法是根据前面的选法推出来的,而且不管你前面选的是什么后面一定不会因为你前面选的东西而改变这个情况。
不满足题意的情况那就是我在同一列选的东西超过了我全部的选的kkk,那么也就是代表的是,我们现在当前这一列选了k/2+1k/2+1k/2+1个以后,在其他列里面无论怎么选,都是符合要求的,也就是我们只用枚举列数就可以
我们可以开三个维度的dp数组,第一个维度代表当前枚举到的行,第二个维度代表的是当前列,我选了多少个,第三个维度代表的是其他列我选了多少个,dp数组的含义就是我当前遍历到的这一行且当前列选了j个,其他列选了k个的一共的种类数。
那么状态转移方程就是
dp[i][j][k]=dp[i−1][j][k]dp[i][j][k]=dp[i-1][j][k]dp[i][j][k]=dp[i−1][j][k]
这个状态就是我什么也不选
如果j>0j>0j>0
dp[i][j][k]+=dp[i−1][j−1][k]∗a[i][u]dp[i][j][k]+=dp[i-1][j-1][k]*a[i][u]dp[i][j][k]+=dp[i−1][j−1][k]∗a[i][u]
代表的是我当前列要选jjj个数,但是上一个状态只选了j−1j-1j−1个因此我这一次要选a[i][j]a[i][j]a[i][j]这个状态的(当前列是uuu)
如果k>0k>0k>0
dp[i][j][k]+=dp[i−1][j][k−1]∗(sum[i]−a[i][u])dp[i][j][k]+=dp[i-1][j][k-1]*(sum[i]-a[i][u])dp[i][j][k]+=dp[i−1][j][k−1]∗(sum[i]−a[i][u])
代表的是我其他列要选kkk个数,但是我上一个状态只选了k−1k-1k−1个数,那么我当前的这一列要选其他数。

#include<iostream>
#include<cstring>
using namespace std;
#define int long long
#define mod 998244353
int dp[51][101][101];
int a[2100][2100];
int sum[210];
signed main(){int n, m;cin >> n >> m;for (int i = 1; i <= n;i++){for (int j = 1; j <= m;j++){cin >> a[i][j];sum[i] += a[i][j];sum[i] %= mod;}}int tot = 0;for (int u = 1; u <= m;u++){memset(dp, 0, sizeof dp);dp[0][0][0] = 1;for (int i = 1; i <= n;i++){for (int j = 0; j <= i;j++){for (int k = 0; k + j <= i;k++){dp[i][j][k] = dp[i - 1][j][k];if(j){dp[i][j][k] += dp[i - 1][j - 1][k] * a[i][u];dp[i][j][k] %= mod;}dp[i][j][k] %= mod;if(k){dp[i][j][k] += dp[i - 1][j][k - 1] * (sum[i] - a[i][u]);dp[i][j][k] %= mod;}dp[i][j][k] %= mod;}}}for (int i = 1; i <= n;i++){for (int j = 0; j + i <= n;j++){if(i>j){tot += dp[n][i][j];tot %= mod;}}}}int ans = 1;for (int i = 1; i <= n;i++){int sum2 = 0;for (int j = 1; j <= m;j++){sum2 += a[i][j];sum2 %= mod;}sum2++;//*********ans *= sum2;ans %= mod;}ans--;//cout << ans << " " << tot << endl;cout << (ans - tot+mod) % mod << endl;
}

当然我们这样是一定超时的,因此我们可以使用差值dp来缩小空间的范围。(+n)是防止出现负数。

#include<iostream>
#include<cstring>
using namespace std;
#define int long long
#define mod 998244353
//int dp[51][101][101];
int dp[101][500];
int a[101][2100];
int sum[210];
signed main(){int n, m;cin >> n >> m;for (int i = 1; i <= n;i++){for (int j = 1; j <= m;j++){cin >> a[i][j];sum[i] += a[i][j];sum[i] %= mod;}}int tot = 0;for (int u = 1; u <= m;u++){memset(dp, 0, sizeof dp);dp[0][n] = 1;for (int i = 1; i <= n;i++){for (int j = -i; j <= i;j++){dp[i][j + n] = dp[i - 1][j + n] + dp[i - 1][j + n-1] * a[i][u] + dp[i - 1][j + 1 + n] * (sum[i] - a[i][u]);dp[i][j+n] %= mod;}}for (int i = n + 1; i <= 2 * n; i++){tot += dp[n][i];tot %= mod;}}//cout << tot << endl;int ans = 1;for (int i = 1; i <= n;i++){int sum2 = 0;for (int j = 1; j <= m;j++){sum2 += a[i][j];sum2 %= mod;}sum2++;ans *= sum2;ans %= mod;}ans--;cout << (ans - tot + mod) % mod << endl;
}

P5664 [CSP-S2019] Emiya 家今天的饭(dp+容斥)相关推荐

  1. 洛谷P5664:Emiya 家今天的饭(容斥、dp)

    解析 应该是比较入门的容斥了 统计方案用总方案数-某列超过1半的方案数 dp设计的一个trick是只统计差值 代码 #include<bits/stdc++.h> using namesp ...

  2. CSPS 2019 Day2 T1 Emiya 家今天的饭(容斥 + 计数 dp)

    Description 给定一个 n×mn \times mn×m 的矩阵,每一行最多选一个数,每一列可以选若干个数,但是每一列选的数不能超总数的一半.求有多少个不同的方案数. Solution 容斥 ...

  3. [CSP day2T1]Emiya 家今天的饭

    Emiya 家今天的饭 题解 挺容易的一道dp,我们可以先考虑容斥.先加上不考虑菜数不超过一半的值,再减去超过一半的部分. 表示在前i种中选j个菜的总种类,这个dp很好想, 下面就是最重要的了. 表示 ...

  4. CSP-S 2019————Emiya 家今天的饭————DP+思维

    题解:本题主要考查DP+思维. 简要题意:一个矩阵,要求每行只选一个节点,每列选的节点不能超过所有选的节点的一半,不能不选,给出每个节点的选择方案数,求总方案数. 1.DP+思维: (1).维护每列已 ...

  5. NOIP2019 Emiya家今天的饭

    NOIP2019 Emiya家今天的饭 ACM退役选手远程口胡 csf如今真的是太菜了,最后16分的做法愣是想了一下午 考虑使用容斥方法: 1 采用动态规划,先求出在无限制情况下,安排kkk种烹饪方法 ...

  6. 【CSP-S2019】D2T1 Emiya 家今天的饭

    CSP-S2019 D2T1 Emiya 家今天的饭 题目 题目描述 Emiya 是个擅长做菜的高中生,他共掌握 nnn 种烹饪方法,且会使用 mmm 种主要食材做菜.为了方便叙述,我们对烹饪方法从 ...

  7. 2019CSP-S Day2T1 Emiya 家今天的饭 题解

    2019CSP-S Day2T1 Emiya 家今天的饭 题解 题目链接 我太菜了 64pts,m<=3m <= 3m<=3. 前64pts数据规模都差不多,因为mmm很小,考虑类似 ...

  8. P5664 [CSP-S2019] Emiya 家今天的饭

    太难惹!!! 文章目录 题目描述 一.分析 二.代码 总结 题目描述 Emiya 是个擅长做菜的高中生,他共掌握 n 种烹饪方法,且会使用 m 种主要食材做菜.为了方便叙述,我们对烹饪方法从 1∼n ...

  9. 【CSP-S 2019 D2 T1】P5664 Emiya 家今天的饭

    HyperlinkHyperlinkHyperlink https://www.luogu.com.cn/problem/P5664 DescriptionDescriptionDescription ...

  10. Emiya家今天的饭

    题目来源: Emiya家的饭 代码 #include <bits/stdc++.h> using namespace std; const int MOD = 998244353; con ...

最新文章

  1. tomcat 如何实现共享jar
  2. JSON字符串的解析
  3. 国外开源威胁情报feed站点 简介
  4. k8s中service类型
  5. Leetcode - 144. Binary Tree Preorder Traversal (层次遍历)
  6. 用python爬虫抓站的一些技巧总结
  7. 1.Jenkins 在windows下的安装与配置
  8. 在MySQL 5.7下排查内存泄露和OOM问题全过程
  9. jquery ajax怎么实现,你认为他有什么不足之处
  10. 判断一个无符号整数是不是2的n次幂的幂
  11. 手机学习android,用手机来学习 学生必备6款Android应用软件
  12. scala上界_Scala方差,上界和下界
  13. cm-14.1 Android系统启动过程分析(二)-Zygote进程启动过程
  14. 腾讯市值首破5000亿美元;阿里224亿港币入股高鑫零售;特斯拉新超跑在华接受预定丨价值早报
  15. Java相关软件下载地址
  16. 华为 应用隐藏大师 计算机,【分享】应用隐藏大师v6.3.1~一键隐藏不想让别人看到的软件...
  17. nuxt 引入第三方字体、艺术字效果
  18. Scratch3.0 二次开发环境部署(一)
  19. Java实现输出水仙花(易懂)
  20. odoo14Vscode调试环境

热门文章

  1. 华硕桌面计算机图标,台式华硕主板Win10系统添加控制面板到桌面?
  2. 云计算平台诸神之战 百家争鸣之势
  3. 4_2. 数据报网络与虚电路网络
  4. 更换芯片stm32f103
  5. ADI的CCES在WINDOWS10下的注册
  6. 利用asp.net core actionfilter实现简单的RBAC权限过滤
  7. 基于vue.js前台美食点菜订餐系统ssm java毕业设计项目有介绍
  8. Python工具源码,Python批量提取PPT文件中的图片
  9. Java工程师面试1000题152-Stream API编程练习
  10. 所需 VMware Tools ISO 映像不存在或无法访问/2003vmtools无法安装