csp2019 Emiya家今天的饭题解

qwq

由于窝太菜了,实在是不会,所以在题解的帮助下过掉了这道题。
写此博客来整理一下思路

正文

传送
简化一下题意:现在有\(n\)行\(m\)列数,选\(k\)个数的合法方案需满足:
1.一行最多选一个
2.一列最多选\(\lfloor \frac{k}{2} \rfloor\)个数
当然,如果你在某一行里选了0,就相当于没有在这一行里选数
选一次对答案的贡献是你选的所有不为零的数的乘积。对于任意的\(k\),只要有合法方案,就能取。
(希望没有把题目变得更复杂叭)
根据上面的要求,我们发现\(k\)的取值范围是\([1,n]\)。而且根据要求2,如果某个方案在满足1的前提下,是不合法的,那么这个方案里面一定有且仅有1列选了超出\(\lfloor \frac{k}{2} \rfloor\)个数,因为不可能有两列选的数同时超过\(\lfloor \frac{k}{2} \rfloor\)个。我们现在知道了不合法方案的一个特征,那么我们不妨试试总方案数-不合法方案数这个思路。

因为 满足1情况的总方案数-满足1而且不合法的方案数=乱选方案数-不满足1或不满足2的方案数 ,所以我们接下来计算方案数都在满足1的条件下来计算。

计算总方案数:设\(all[i][j]\)表示前\(i\)行,每行至多选一个,一共选了\(j\)个的方案数,那么\(all[i][j]=all[i-1][j]+\sum_{l=1}^m{all[i-1][j-1] \times a[i][l]}\)。用\(sum[i]\)表示第\(i\)行所有数的和,那么\(all[i][j]=all[i-1][j]+all[i-1][j-1] \times sum[i]\)

我们再来看看不合法方案怎么算。上面说到一个不合法方案一定只有1行选的数超过了\(\lfloor \frac{k}{2} \rfloor\)个,所以我们可以枚举每一列。但是我们不知道\(k\)。那么我们可以设\(no[i][j][l]\)表示前\(i\)行,该列选了\(j\)个,其他列选了\(l\)个。\(no[i][j][l]=no[i-1][j][l]+no[i-1][j-1][l]\times a[i][j]+no[i-1][j][l-1] \times(sum[i]-a[i][j])\)这样就可以由\(j,l\)确定唯一的\(k\)。枚举列:\(O(m)\),枚举\(i\):\(O(n)\),因为选数的个数最多是\(n\),所以枚举\(j,l\)都是\(O(n)\),总复杂度\(O(mn^3)\)

显然是不够的,需要优化。发现我们其实并不需要具体的\(k\),只需要知道当前列和其他列选的数的差值即可。为什么呢?不妨设当前列选的数为\(x+j\)个,其他列选的数为\(x\)个,那么一共选的数就是\(2x+j\)个。那么这个方案对于\(k \in [\lfloor \frac{2x}{2} \rfloor,\lfloor \frac{2x+j}{2} \rfloor]\)都是不合法的。这里\(x\)取值任意,所以可以覆盖所有的\(k\)。所以设\(no[i][j]\)表示前\(i\)行,当前枚举的列比其他列多选了\(j\)个的方案数。
\(no[i][j]=no[i-1][j]+no[i-1][j-1] \times a[i][j]+no[i-1][j+1] \times (sum[i]-a[i][j])\)
注意这里有个坑:枚举到第\(i\)行的时候,当前列最多会比其他列少\(i\)个数,所以\(j\)应该从\(-i\)开始枚举,而不是0。考虑到不能出现负下标,所以在代码中将每个下标+n。
如果这个方案是不合法方案,那么对应的\(j\)一定大于0。
最终答案就是\(sum_{j=1}^n{all[n][j]}-\sum_{j=1}^n{no[n][j]}\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ll read()
{
    char ch=getchar();
    ll x=0;bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return f?-x:x;
}
const ll mod=998244353;
ll n,m,a[209][2009],sum[109],all[209][2009];
ll no[109][2109];
ll ans;
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
      a[i][j]=read(),sum[i]=(sum[i]+a[i][j])%mod;//保险起见随时随地模一下
    all[0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=n;j++)
            all[i][j]=(all[i-1][j]+all[i-1][j-1]*sum[i]%mod+mod)%mod;
    for(int j=1;j<=n;j++)
     ans=(ans+all[n][j])%mod;
    for(int lie=1;lie<=m;lie++)
    {
        memset(no,0,sizeof(no));
        no[0][n]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=n-i;j<=n+i;j++)
           {
             no[i][j]=(no[i-1][j]+no[i-1][j-1]*a[i][lie]%mod+no[i-1][j+1]*(sum[i]-a[i][lie])%mod+mod)%mod;
           }
        }
        for(int j=n+1;j<=2*n;j++)
         ans=(ans-no[n][j]+mod)%mod;
    }
    cout<<ans;
    return 0;
}

原文地址:https://www.cnblogs.com/lcez56jsy/p/12079053.html

时间: 2024-10-08 16:40:41

csp2019 Emiya家今天的饭题解的相关文章

CSP2019 Emiya 家今天的饭

Description: 有 \(n\) 中烹饪方法和 \(m\) 种食材,要求: 至少做一种菜 所有菜的烹饪方法各不相同 同种食材的菜的数量不能超过总菜数的一半 求做菜的方案数. Solution1:考虑 DP 先容斥一下,答案为忽略第三个条件所得的方案数减去每一种食材超过一半的方案数之和. 忽略掉第三个条件之后答案显然是 \[ \prod_{i=1}^n(1+\sum_{j=1}^m a_{i,j})-1 \] 减去 1 是去掉一道菜都不做的方案. 枚举每一列超过一半的情况,显然,除这一列外

CSP-S 2019 Emiya 家今天的饭

\(\text {Emiya 家今天的饭}\) Emiya 不会让大家饿肚子,所以将做至少一道菜,即 \(k\geq1\) Rin 希望品尝不同烹饪方法做出的菜,因此她要求每道菜的烹饪方法互不相同 Yazid 不希望品尝太多同一食材做出的菜,因此他要求每种主要食材至多在一半的菜(即\(?k /2?\)道菜)中被使用 subtask1 \(\text {期望得分 64pts}\) \(f[i][j][k][l]\)\(j, k, l\)分别表示每一列选多少数就行了 subtask2 \(\text

【JZOJ6433】【luoguP5664】【CSP-S2019】Emiya 家今天的饭

description analysis 首先可以知道不符合要求的食材仅有一个,于是可以容斥拿总方案数减去选不合法食材的不合法方案数 枚举选取哪一个不合法食材,设\(f[i][j]\)表示到第\(i\)种烹饪方法.操作权值为\(j\)的方案数 给每一个操作赋权值,选当前行合法食材列为\(0\),不选当前行为\(1\),选当前行不合法食材列为\(2\) 转移是比较容易的,可知选当前列为不合法食材的方案数就是\(\sum_{i=n+1}^{2n}f[n][i]\) code #include<std

CSP2019 题解

CSP2019 题解 D1T1 格雷码(code) 题目传送门 https://loj.ac/problem/3208 题解 按照题意模拟就可以了. 对于第 \(i\) 位,如果 \(k \geq 2^i\) 那么这一位就是 \(1\),然后把 \(k\) 变成 \(2^{i + 1} - k - 1\).否则这一位为 \(0\),\(k\) 不变. 代码 https://loj.ac/submission/687508 D1T2 括号树(brackets) 题目传送门 https://loj.

CSP2019题解

按照CSP题目顺序来写 格雷码 不难发现答案可以递归找到,然后每一次做即可. 代码 括号树 简单题,直接在树上搞一个栈然后回溯即可. 括号树nmsl 代码 树上的数 咕咕咕 Emiya 家今天的饭 很显然可以看出这题可以容斥,然后就可以写一个\(O(mn^3)\)的\(dp\). 然后考虑后面那两维状态可以做一个差,这样子就优化成了\(O(2mn^2)\),然后就可以过了. 代码 划分 \(\texttt{__int128}\)不香吗 代码 树的重心 代码 原文地址:https://www.cn

CSP2019复赛游记

目录 Day -1 Day 0 Day 1 考前 考中 考后 做法&程序(考场做法,不能AC) 格雷码 括号树 树上的数 Day 2 考前 考中 考后 做法&程序(考场做法,不能AC) Emiya 家今天的饭 划分 树的重心 Day 3+(后记&提醒) date: 2019-11-15 前言:想直接进入正题请跳转到Day 1. Day -1 明天我就去南京了,感到非常的紧张,毕竟CSP和NOIP没有关系,没有真题可以刷(逃. 注:对于内心中难度的比较,是对于NOIP提高组的题目比较

CSP-J/S2019试题选做

小蒟蒻duyi CSP爆炸之后一直在颓,所以直到最近才陆续订正完CSP的题/kel 以后不能这么颓了(flag) S D1T2 括号树 设\(f[u]\)表示根到\(u\)的路径上有多少子串是合法括号串.(即题目里的\(k_u\),此变量名缺乏个性,故换之) 从根向每个节点dfs,容易求出\(c[u]\):表示从根到\(u\)的路径上,我们能匹配则匹配,最后剩下多少个待匹配的左括号. 例如如下\(s_u\)对应的\(c[u]\): ((() \(c[u]=2\). (())( \(c[u]=1\

张书乐:想在中国开149家店,宜家的肉丸生意快做不下去了

在后流量时代,宜家对更多场景的渴望,已经不是一个店面能包容的了.它不得不依托巨大的线下人流,寻找更多市场红利. 文/张书乐 刊载于<商界评论>2017年2月刊 据宜家家居公布的2016财年报告显示,宜家集团总收入达351亿欧元,比上年增长了7.4%:宜家中国销售额超过125亿人民币,比于去年增长了18.9%.宜家集团今年全球商场共计迎来7.83亿人次的到访,而宜家中国每分钟就会迎来339位顾客,比去年增加20%.在该公司全球28个市场中,中国增长最快. 一连串利好的上扬数据,尤其是在中国市场的

周爱民:真正的架构师是没有title的(图灵访谈)

周爱民,现任豌豆荚架构师,国内软件开发界资深软件工程师.从1996年起开始涉足商业软件开发,历任部门经理.区域总经理.高级软件工程师.平台架构师等职,有18年的软件开发与架构.项目管理及团队建设经验,曾任盛大网络平台架构师.支付宝业务架构师,是 Borland Delphi 产品技术专家,也是 Qomo 开源项目(JavaScript)的发起者.2003年5月被美国 Borland 公司授予「Borland Delphi 产品专家」称号,并授予「论坛特别贡献奖」.著有<大道至简——软件工程实践者