Solution -「ABC 215H」Cabbage Master
\(\mathcal{Description}\)
Link.
有 \(n\) 种颜色的,第 \(i\) 种有 \(a_i\) 个,任意两球互不相同。还有 \(m\) 个盒子,每个盒子可以被放入某些颜色的小球,且第 \(i\) 个盒子要求放入总数不少于 \(b_i\)。你要拿走尽量少的球,使得要求无法被满足,并求出此时拿球方案数模 \(998244353\) 的值。
\(n\le20\),\(m\le10^4\)。
\(\mathcal{Solution}\)
如果保持清醒地做这道题还是比较简单的。
首先用 Hall 定理转化合法条件,记 \(A=\{a_n\}\),\(B=\{b_m\}\),\(\operatorname{adj}(S\subseteq B)\) 表示 \(S\) 内的 \(b\) 所邻接的 \(a\) 的并,则合法条件为
\]
那么可以得知非法条件。固定 \(\operatorname{adj}(S)\),显然 \(b\) 能多选就多选,最终能得到最小取球数量为
\]
令集族 \(\mathcal S=\arg \min_{\operatorname{adj}(S)}\left\{\sum_{a\in\operatorname{adj}(S)}a-\sum_{\operatorname{adj}(\{b\})\subseteq\operatorname{adj}(S)}b+1\right\}\),也能避免算重地求出方案数为:
\]
其中 \(f(T,c)\) 表示在集合 \(T\) 内的 \(a\) 中一共选走 \(c\) 个,且每个 \(a\) 至少被选走一个的方案数,可以容斥计算。具体实现上,用几次 FWT 即可。复杂度 \(\mathcal O(nm+2^nn)\)。
\(\mathcal{Code}\)
/*~Rainybunny~*/
#include <cstdio>
#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
inline void chkmin( int& a, const int b ) { b < a && ( a = b ); }
const int MAXN = 20, MAXM = 1e4, MAXV = 2e6, MOD = 998244353;
int n, m, a[MAXN + 5], b[MAXM + 5], adj[MAXM + 5], sum[1 << MAXN];
int fac[MAXV + 5], ifac[MAXV + 5], tot[1 << MAXN];
int cvr[1 << MAXN], chs[1 << MAXN];
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline int mul( const long long a, const int b ) { return int( a * b % MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
inline int mpow( int a, int b ) {
int ret = 1;
for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
return ret;
}
inline void init( const int s ) {
fac[0] = 1;
rep ( i, 1, s ) fac[i] = mul( i, fac[i - 1] );
ifac[s] = mpow( fac[s], MOD - 2 );
per ( i, s - 1, 0 ) ifac[i] = mul( ifac[i + 1], i + 1 );
}
inline int comb( const int a, const int b ) {
return a < b ? 0 : mul( fac[a], mul( ifac[b], ifac[a - b] ) );
}
inline void fwtAND( const int len, int* u, const auto& adf ) {
for ( int stp = 1; stp < len; stp <<= 1 ) {
for ( int i = 0; i < len; i += stp << 1 ) {
rep ( j, i, i + stp - 1 ) {
adf( u[j], u[j + stp] );
}
}
}
}
inline void fwtOR( const int len, int* u, const auto& adf ) {
for ( int stp = 1; stp < len; stp <<= 1 ) {
for ( int i = 0; i < len; i += stp << 1 ) {
rep ( j, i, i + stp - 1 ) {
adf( u[j + stp], u[j] );
}
}
}
}
int main() {
scanf( "%d %d", &n, &m );
rep ( i, 0, n - 1 ) scanf( "%d", &a[i] );
rep ( i, 0, m - 1 ) scanf( "%d", &b[i] );
rep ( i, 0, n - 1 ) {
rep ( j, 0, m - 1 ) {
int t; scanf( "%d", &t );
adj[j] |= t << i;
}
}
rep ( i, 0, m - 1 ) sum[adj[i]] += b[i];
fwtOR( 1 << n, sum, []( int& u, const int v ) { u += v; } );
int tak = 1e9;
rep ( S, 1, ( 1 << n ) - 1 ) {
rep ( i, 0, n - 1 ) if ( S >> i & 1 ) tot[S] += a[i];
if ( sum[S] ) chkmin( tak, tot[S] + 1 - sum[S] );
}
if ( tak <= 0 ) return puts( "0 1" ), 0;
printf( "%d ", tak );
int way = 0; init( tot[( 1 << n ) - 1] );
rep ( S, 1, ( 1 << n ) - 1 ) {
cvr[S] = tot[S] + 1 - sum[S] == tak;
chs[S] = comb( tot[S], tak );
if ( __builtin_popcount( S ) & 1 ) chs[S] = sub( 0, chs[S] );
}
fwtAND( 1 << n, cvr, []( int& u, const int v ) { u += v; } );
fwtOR( 1 << n, chs, addeq );
rep ( S, 1, ( 1 << n ) - 1 ) if ( cvr[S] ) {
( __builtin_popcount( S ) & 1 ? subeq : addeq )( way, chs[S] );
}
printf( "%d\n", way );
return 0;
}
\(\mathcal{Details}\)
某个问题无法找到解决方法时,尤其是在速度相关的比赛时,一定要冷静下来,形式地描述“我想要求什么东西”,而不是对着代码修修补补。
Solution -「ABC 215H」Cabbage Master的更多相关文章
- Solution -「ABC 219H」Candles
\(\mathcal{Description}\) Link. 有 \(n\) 支蜡烛,第 \(i\) 支的坐标为 \(x_i\),初始长度为 \(a_i\),每单位时间燃烧变短 \(1\) ...
- Solution -「ABC 213G」Connectivity 2
\(\mathcal{Description}\) Link. 给定简单无向图 \(G=(V,E)\),点的编号从 \(1\) 到 \(|V|=n\).对于 \(k=2..n\),求 \(H= ...
- Solution -「ABC 213H」Stroll
\(\mathcal{Description}\) Link. 给定一个含 \(n\) 个结点 \(m\) 条边的简单无向图,每条边的边权是一个常数项为 \(0\) 的 \(T\) 次多项式, ...
- Solution -「ABC 217」题解
D - Cutting Woods 记录每一个切割点,每次求前驱后驱就好了,注意简单判断一下开闭区间. 考场上采用的 FHQ_Treap 无脑莽. #include <cstdio> #i ...
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- Solution Set -「ABC 217」
大家好屑兔子又来啦! [A - Lexicographic Order] 说个笑话,\(\color{black}{\text{W}}\color{red}{\text{alkingDead} ...
- Solution -「ARC 110E」Shorten ABC
\(\mathcal{Description}\) Link. 给定长度为 \(n\),包含 A, B, C 三种字符的字符串 \(S\),定义一次操作为将其中相邻两个不相同的字符替换为字符集 ...
- Solution -「CTS 2019」「洛谷 P5404」氪金手游
\(\mathcal{Description}\) Link. 有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
随机推荐
- 华为云 Kubernetes 管理员实训 五 课后作业
练习1 部署一个Deployment应用,使用secret普通卷,该应用启动依赖此secret. Deployment的名称为<hwcka-005-1-你的华为云id> 将所用命令.创建的 ...
- jsp文件中文乱码解决
文件顶加上 <%@ page contentType="text/html;charset=UTF-8" language="java" %>即可
- IDEA开启热部署
双击shift,查找Registry
- vue 使用mock来模拟数据
首先,需要安装mock npm install mockjs --save-dev 在main.js中引入mock mock文件写法如下: const Mock = require('mockjs') ...
- hdfs文件导入到hive(带资源)
前言 hive是基于Hadoop的一个数据仓库工具,用来进行数据提取.转化.加载,这是一种可以存储.查询和分析存储在Hadoop中的大规模数据的机制.hive数据仓库工具能将结构化的数据文件映射为一张 ...
- 5.12-jsp分页功能学习
1.分页功能相关资料查询 分页须知知识点: (1)JDBC2.0的可滚动结果集. (2)HTTP GET请求. 一.可滚动结果集 Connection con = DriverManager.g ...
- 技巧02--Terminal Preview优化
0x00 下载安装 可在MS应用商店安装,也可以直接百度下载安装包安装 0x01 设置默认自启 0x02 Terminal Preview美化 1.打开终端settings 2.点击这个Open JS ...
- 推荐召回--基于内容的召回:Content Based
目录 1. 前言 2. 构建画像 3. 内容召回的算法 1. 前言 在之前总结过协同过滤的召回通路后,今天我们来总结下召回策略中的重头戏:基于内容的召回通路,也即我们常说的基于标签的召回.这里就要涉及 ...
- js-reduce方法源码
// 数组中的reduce方法源码复写 //先说明一下reduce原理:总的一句,reduce方法主要是把数组遍历, //然后把数组的每个元素传入回调函数中,回调函数怎么处理,就会的到什么样的效果 A ...
- 不使用pvc的方式在K8S中部署apisix-gateway
不使用pvc的方式在K8S中部署apisix-gateway 简介 我的apisix使用etcd作为数据存储服务器,官方的使用pvc方式或者docker-compose的方式,对于新手不太友好,本篇是 ...