CSPS 2019 Day2 T1 Emiya 家今天的饭(容斥 + 计数 dp)
Description
给定一个 n×mn \times mn×m 的矩阵,每一行最多选一个数,每一列可以选若干个数,但是每一列选的数不能超总数的一半。求有多少个不同的方案数。
Solution
容斥 + 计数 dp。ans=ans =ans= 全部的方案数 −-− 超过 ⌊k2⌋\lfloor \frac{k}{2 }\rfloor⌊2k⌋ 的方案数。
令 sumisum_isumi 为
sumi=∑j=1mai,jsum_i = \sum_{j=1}^m a_{i,j} sumi=j=1∑mai,j
全部的方案数即为
∏i=1n(sumi+1)−1\prod_{i=1}^n (sum_i + 1) - 1 i=1∏n(sumi+1)−1
用计数 dp 求超过 ⌊k2⌋\lfloor \frac{k}{2 }\rfloor⌊2k⌋ 的方案数。枚举一个列,令 fi,j,kf_{i,j,k}fi,j,k 为在前 iii 行中,枚举的列选了 jjj 个,其他列选了 kkk 个的方案数。转移为
fi,j,k=fi−1,j,k+fi−1,j−1,k×ai,j+fi−1,j,k−1×(sumi−ai,j)f_{i,j,k} = f_{i - 1, j, k} + f_{i - 1, j - 1, k} \times a_{i,j} + f_{i - 1, j, k - 1} \times (sum_i - a_{i,j}) fi,j,k=fi−1,j,k+fi−1,j−1,k×ai,j+fi−1,j,k−1×(sumi−ai,j)
超过 ⌊k2⌋\lfloor \frac{k}{2 }\rfloor⌊2k⌋ 的方案数为
∑j>kfn,j,k\sum_{j>k} f_{n,j,k} j>k∑fn,j,k
如何优化?j,kj,kj,k 两维换成 j−kj - kj−k。为什么?每一层转移中 j−kj - kj−k 不相同 ,统计答案时只计算了 j−k>0j - k > 0j−k>0 的部分。
枚举一个列,令 fi,kf_{i,k}fi,k 为在前 iii 行中,枚举的列选了比其他列多选了 kkk 个的方案数。转移为
fi,k=fi−1,k+fi−1,k−1×ai,k+fi−1,k+1×(sumi−ai,k)f_{i,k} = f_{i-1,k} + f_{i-1,k-1} \times a_{i,k} + f_{i-1,k+1} \times (sum_i - a_{i,k}) fi,k=fi−1,k+fi−1,k−1×ai,k+fi−1,k+1×(sumi−ai,k)
综上所述
ans=∏i=1n(sumi+1)−1−∑i=1nfn,ians = \prod_{i=1}^n (sum_i + 1) - 1 - \sum_{i=1}^n f_{n,i} ans=i=1∏n(sumi+1)−1−i=1∑nfn,i
细节问题如初值,对负值增加一个偏移量,详见代码。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100 + 5, M = 2000 + 5, p = 998244353;
ll all = 1, ans, f[N][N + N], a[N][M], sum[N];
int n, m;
int main(){scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++)scanf("%lld", &a[i][j]), sum[i] = (sum[i] + a[i][j]) % p;all = all * (sum[i] + 1) % p;}for (int j = 1; j <= m; j++) {f[0][N] = 1;for (int i = 1; i <= n; i++)for (int k = -n + N; k <= n + N; k++)f[i][k] = (f[i - 1][k] + f[i - 1][k - 1] * a[i][j] % p + f[i - 1][k + 1] * (sum[i] - a[i][j]) % p) % p;for (int i = 1; i <= n; i++) ans = (ans + f[n][i + N]) % p;}printf("%lld\n", (all - ans - 1 + p) % p);return 0;
}
CSPS 2019 Day2 T1 Emiya 家今天的饭(容斥 + 计数 dp)相关推荐
- 2019 CSP-S Day2 T1 Emiya 家今天的饭(DP)
题目 Description Input Output 输出到文件 meal.out 中. 仅一行一个整数,表示所求方案数对 998, 244, 353 取模的结果. Sample Input Sam ...
- (2019Csp_s D2 T1)Emiya 家今天的饭
本题主要考查滚动数组 dpi,j,kdp_{i,j,k}dpi,j,k表示前iii种烹饪方法,假设最多的是食材jjj,食材jjj比其他食材多kkk次出现 其中i∈[1,n],j∈[1,m],k∈[− ...
- NOIP2019 Emiya家今天的饭
NOIP2019 Emiya家今天的饭 ACM退役选手远程口胡 csf如今真的是太菜了,最后16分的做法愣是想了一下午 考虑使用容斥方法: 1 采用动态规划,先求出在无限制情况下,安排kkk种烹饪方法 ...
- 【CSP-S2019】D2T1 Emiya 家今天的饭
CSP-S2019 D2T1 Emiya 家今天的饭 题目 题目描述 Emiya 是个擅长做菜的高中生,他共掌握 nnn 种烹饪方法,且会使用 mmm 种主要食材做菜.为了方便叙述,我们对烹饪方法从 ...
- [CSP day2T1]Emiya 家今天的饭
Emiya 家今天的饭 题解 挺容易的一道dp,我们可以先考虑容斥.先加上不考虑菜数不超过一半的值,再减去超过一半的部分. 表示在前i种中选j个菜的总种类,这个dp很好想, 下面就是最重要的了. 表示 ...
- 2019CSP-S Day2T1 Emiya 家今天的饭 题解
2019CSP-S Day2T1 Emiya 家今天的饭 题解 题目链接 我太菜了 64pts,m<=3m <= 3m<=3. 前64pts数据规模都差不多,因为mmm很小,考虑类似 ...
- Emiya 家今天的饭(CSP 2019 D2 T1)
题目 题目描述 Emiya 是个擅长做菜的高中生,他共掌握 nn 种烹饪方法,且会使用 mm 种主要食材做菜.为了方便叙述,我们对烹饪方法从 1 \sim n1∼n 编号,对主要食材从 1 \sim ...
- Emiya家今天的饭
题目来源: Emiya家的饭 代码 #include <bits/stdc++.h> using namespace std; const int MOD = 998244353; con ...
- P5664 [CSP-S2019] Emiya 家今天的饭
太难惹!!! 文章目录 题目描述 一.分析 二.代码 总结 题目描述 Emiya 是个擅长做菜的高中生,他共掌握 n 种烹饪方法,且会使用 m 种主要食材做菜.为了方便叙述,我们对烹饪方法从 1∼n ...
最新文章
- C语言指针表示二维数组的方法!_只愿与一人十指紧扣_新浪博客
- nc65语义模型设计_完整word版,NC数据加工做语义模型
- 变了,iPhone 12变身iPhone 4模样;下一代只支持单种5G频段?
- Qt4访问sqlite数据库
- div不占位置_Python爬取校花网,妈妈再也不会担心我不给她发女朋友照片了
- 计算机图形学代码之三角形绘制
- 用手机做电脑摄像头的软件
- crazybox路由器解决授权码问题
- 完全卸载迈克菲Mcafee的工具
- Axure RP小部件使用教程
- 水彩风建筑效果图制作教程
- Photoshop CS 5 注册方法
- Unity制作简单的精灵图动画(新手向)
- 聆听C++语言创建者的教诲
- Android学习之管理Activity的生命周期
- 【可视化】对比与位置的艺术 - how we position and what we compare
- 计算机二维动画制作流程,计算机二维动画制作的特点
- 2021年全球与中国汽车LED驱动器行业市场规模及发展前景分析
- 【算法•日更•第九期】树型动态规划详解:二叉苹果树
- [译]用C#创建一个屏幕保护程序