当前位置: 首页 > news >正文

解题报告-P5664 [CSP-S2019] Emiya 家今天的饭

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

题目描述

Emiya 是个擅长做菜的高中生,他共掌握 \(n\)烹饪方法,且会使用 \(m\)主要食材做菜。为了方便叙述,我们对烹饪方法从 \(1 \sim n\) 编号,对主要食材从 \(1 \sim m\) 编号。

Emiya 做的每道菜都将使用恰好一种烹饪方法与恰好一种主要食材。更具体地,Emiya 会做 \(a_{i,j}\) 道不同的使用烹饪方法 \(i\) 和主要食材 \(j\) 的菜(\(1 \leq i \leq n\)\(1 \leq j \leq m\)),这也意味着 Emiya 总共会做 \(\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m} a_{i,j}\) 道不同的菜。

Emiya 今天要准备一桌饭招待 Yazid 和 Rin 这对好朋友,然而三个人对菜的搭配有不同的要求,更具体地,对于一种包含 \(k\) 道菜的搭配方案而言:

  • Emiya 不会让大家饿肚子,所以将做至少一道菜,即 \(k \geq 1\)
  • Rin 希望品尝不同烹饪方法做出的菜,因此她要求每道菜的烹饪方法互不相同
  • Yazid 不希望品尝太多同一食材做出的菜,因此他要求每种主要食材至多在一半的菜(即 \(\lfloor \frac{k}{2} \rfloor\) 道菜)中被使用

这里的 \(\lfloor x \rfloor\) 为下取整函数,表示不超过 \(x\) 的最大整数。

这些要求难不倒 Emiya,但他想知道共有多少种不同的符合要求的搭配方案。两种方案不同,当且仅当存在至少一道菜在一种方案中出现,而不在另一种方案中出现。

Emiya 找到了你,请你帮他计算,你只需要告诉他符合所有要求的搭配方案数对质数 \(998,244,353\) 取模的结果。

输入格式

第 1 行两个用单个空格隔开的整数 \(n,m\)

第 2 行至第 \(n + 1\) 行,每行 \(m\) 个用单个空格隔开的整数,其中第 \(i + 1\) 行的 \(m\) 个数依次为 \(a_{i,1}, a_{i,2}, \cdots, a_{i,m}\)

输出格式

仅一行一个整数,表示所求方案数对 \(998,244,353\) 取模的结果。

输入输出样例 #1

输入 #1

2 3 
1 0 1
0 1 1

输出 #1

3

输入输出样例 #2

输入 #2

3 3
1 2 3
4 5 0
6 0 0

输出 #2

190

输入输出样例 #3

输入 #3

5 5
1 0 0 1 1
0 1 0 1 0
1 1 1 1 0
1 0 1 0 1
0 1 1 0 1

输出 #3

742

说明/提示

【样例 1 解释】

由于在这个样例中,对于每组 \(i, j\),Emiya 都最多只会做一道菜,因此我们直接通过给出烹饪方法、主要食材的编号来描述一道菜。

符合要求的方案包括:

  • 做一道用烹饪方法 1、主要食材 1 的菜和一道用烹饪方法 2、主要食材 2 的菜
  • 做一道用烹饪方法 1、主要食材 1 的菜和一道用烹饪方法 2、主要食材 3 的菜
  • 做一道用烹饪方法 1、主要食材 3 的菜和一道用烹饪方法 2、主要食材 2 的菜

因此输出结果为 \(3 \bmod 998,244,353 = 3\)。 需要注意的是,所有只包含一道菜的方案都是不符合要求的,因为唯一的主要食材在超过一半的菜中出现,这不满足 Yazid 的要求。

【样例 2 解释】

Emiya 必须至少做 \(2\) 道菜。

\(2\) 道菜的符合要求的方案数为 \(100\)

\(3\) 道菜的符合要求的方案数为 \(90\)

因此符合要求的方案数为 \(100 + 90 = 190\)

【数据范围】

::cute-table{tuack}

测试点编号 \(n=\) \(m=\) \(a_{i,j}<\)
\(1\) \(2\) \(2\) \(2\)
\(2\) ^ \(3\) ^
\(3\) \(5\) \(2\) ^
\(4\) ^ \(3\) ^
\(5\) \(10\) \(2\) ^
\(6\) ^ \(3\) ^
\(7\) \(10\) \(2\) \(1000\)
\(8\) ^ \(3\) ^
\(9\sim 12\) \(40\) \(2\) ^
\(13\sim16\) ^ \(3\) ^
\(17\sim21\) ^ \(500\) ^
\(22\sim25\) \(100\) \(2000\) \(998,244,353\)

对于所有测试点,保证 \(1 \leq n \leq 100\)\(1 \leq m \leq 2000\)\(0 \leq a_{i,j} \lt 998,244,353\)


解题报告

参考题解:题解 P5664

好的,我还是一碰 DP 就死呢(无言了)。

考虑对题目中的限制作进一步的表述。

其中,对于列的性质,发现若有不合法的列,则必然有且仅有一列不合法,这是因为不可能有不同的两列的数量都大于总数的一半。

发现列的限制很容易容斥:每行选不超过一个的方案数 \(-\) 每行选不超过一个,且某一列选了超过一半的方案数。

那么直接枚举不合法的列 \(t\),我们就只关心一个数的位置是否在当前列;如果属于在其他列的情况,那么它具体在哪一列对当前列的合法性并无影响,我们并不需要考虑。

设计状态:\(dp_{i,j,k}\) 表示对于非法列 \(t\),前 \(i\) 行选了 \(j\) 个在该列,选了 \(k\) 个在其他列,另设 \(s_i\) 表示第 \(i\) 的总和,那么有:

\[dp_{i,j,k}=dp_{i-1,j,k}+a_{i,t} \times dp_{i-1,j-1,k}+(s_i-a_{i,t}) \times dp_{i-1,j,k-1} \]

非法的方案数就是累加每一个列 \(t\)\(\sum_{j>k} dp_{n,j,k}\)

接下来考虑计算总方案数:和之前相似,只需设 \(g_{i,j}\) 为前 \(i\) 行共选了 \(j\) 个数的方案数,则有转移:

\[g_{i,j}=g_{i-1,j}+s_i \times g_{i-1,j-1} \]

那么 \(\sum_{i=1}^{n} g_{n,i}\) 就是总方案数, 这一步是 \(O(n^2)\) 的。所以现在可以在 \(O(mn^3)\) 的总复杂度内完成这题。

进一步优化,注意到在不合法情况的计算过程中,我们实际上并不关心 \(j\)\(k\) 的具体数值,而只关心相对的大小关系

那么我们可以重新设 \(dp_{i,j}\) 表示表示前 \(i\) 行,当前列的数比其他列的数多了 \(j\) 个,则有:

\[dp_{i,j}=dp_{i-1,j}+a_{i,t} \times dp_{i-1,j-1}+(s_i-a_{i,t}) \times dp_{i-1,j+1} \]

复杂度 \(O(mn^2)\),代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=998244353;
const int N=110;
const int M=4110;#define ckmax(x,y) ( x=max(x,y) )
#define ckmin(x,y) ( x=min(x,y) )
#define Add(x,y) ( x=(x+y)%mod )inline int read()
{int f=1,x=0; char ch=getchar();while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }while(isdigit(ch))  { x=x*10+ch-'0';    ch=getchar(); }return f*x;
}int n,m,ans;
int w[N][M],s[N][M];
int dp[N][M],g[N][M];signed main()
{// freopen("P5664.in","r",stdin);// freopen("P5664.out","w",stdout);n=read(),m=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){w[i][j]=read();Add(s[i][0],w[i][j]);}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)s[i][j]=(s[i][0]-w[i][j]+mod)%mod;for(int k=1;k<=m;k++){memset(dp,0,sizeof(dp)); dp[0][n]=1;for(int i=1;i<=n;i++)for(int j=n-i;j<=n+i;j++)dp[i][j]=( dp[i-1][j]+dp[i-1][j-1]*w[i][k]%mod+dp[i-1][j+1]*s[i][k]%mod )%mod;for(int i=1;i<=n;i++) Add(ans,dp[n][i+n]);}g[0][0]=1;for(int i=1;i<=n;i++)for(int j=0;j<=n;j++)g[i][j]=( g[i-1][j]+(j>0 ? g[i-1][j-1]*s[i][0]%mod:0) )%mod;for(int i=1;i<=n;i++) ans=(ans-g[n][i]+mod)%mod;printf("%lld\n",ans*(mod-1)%mod);return 0;
}
http://www.hskmm.com/?act=detail&tid=31084

相关文章:

  • object类
  • Day 10
  • 2025 年生态格宾网厂家推荐榜:格宾网石笼/格宾网护坡/格宾网挡墙/格宾网网箱厂家推荐,聚焦工程安全与生态保护,助力基建项目高效落地
  • 时序博弈算法荣获时间检验奖
  • 背叛 仇恨 消极 如刀子刺穿了铁心 嘲笑 嗤之以鼻 漠然后只剩下孤寂
  • STM32主控芯片硬件设计总结
  • 亚马逊因暗黑模式订阅设计支付25亿美元和解金
  • P6645 [CCO 2020] Interval Collection
  • 2025年排烟风机厂家推荐榜:混流风机|管道风机|排烟风机|离心风机|轴流风机|轴流风机厂家,专注高效消防与节能,助力多行业绿色升级
  • 【通达信L2黑科技】 用 DLL 把 10 年机构大单净额 1 秒拖进本地,选股、排序、回测快到飞起!
  • 详细介绍:iCloud照片共享:在家庭内外分享iCloud照片
  • 对static新的认识
  • 2025年氧化镁厂家最新推荐排行榜,电工级/高温/低温/中温/防火电缆/矿物绝缘/熔盐加热器/电热管用/单头管用/合成云母用氧化镁公司推荐!
  • 智能体分析
  • 2025 年玄武岩厂家推荐榜:玄武岩/0-3mm/3-5mm/5-10mm/10-15mm/10-20mm/石子厂,聚焦基建升级与高端化需求,山东展飞建筑材料有限公司成优选
  • 2025 佛山铝合金/系统/断桥铝/耐用/推拉/封阳台/别墅/静音门窗厂家品牌实力推荐:聚焦技术与服务的五大优选标杆
  • Ubuntu22.04 server网络配置
  • 完整教程:深度学习优化器全面指南:核心参数选择与实战策略
  • 说说新版畅联云的一些重要约定
  • App.vue(完整可运行示例)
  • Windows MySQL 报错
  • agents.md和codex.md的关系:codex本尊直接答复
  • ARC/CF记录
  • 台式机电脑装win10哪个版本好_台式机电脑装win10专业版教程 - 教程
  • Avalonia Behaviors 在 StackPanel 空白处无效问题解析与解决方案
  • 完整教程:Django 入门:快速构建 Python Web 应用的强大框架
  • 高级语言程序设计第一节课作业
  • Hyperliquid 的稳定币USDH发行机制与发行商竞选指南
  • windows上建立的ssh版git仓库的服务器
  • 2025年聚合硫酸铁供应厂家如何选?行业权威指南与成本控制策略?