首页 > 其他分享 >AtCoder Beginner Contest 215 H Cabbage Master

AtCoder Beginner Contest 215 H Cabbage Master

时间:2023-06-14 13:33:05浏览次数:54  
标签:AtCoder typedef 215 Beginner limits sum maxm subseteq ll

洛谷传送门

AtCoder 传送门

考虑第一问。

发现这个东西长得很像二分图匹配,考虑建图,第 \(i\) 个盒子建 \(b_i\) 个左部点,第 \(i\) 个球建 \(a_i\) 个右部点,每个盒子的每个点往可以放的球的每个点连边。显然要求能被满足等价于,这个二分图存在一个左部点的完全匹配。

因为一个盒子的点本质相同,可以放一起考虑。根据 Hall 定理,要求能被满足的充要条件是 \(\forall T \subseteq \{1, 2, ..., m\}, \sum\limits_{x \in T} b_x \le \sum\limits_{x \in N(T)} a_x\),其中 \(N(T)\) 为 \(T\) 连向的右部点集合。

现在想删除最少个数的点,使得这个条件不满足。显然答案是 \(\min\limits_{T} (\sum\limits_{x \in N(T)} a_x - \sum\limits_{x \in T} b_x + 1)\)。

但是显然不能直接枚举 \(T\)。考虑枚举 \(N(T)\),那么对应的 \(\sum\limits_{x \in T} b_x\) 可以一遍高维前缀和求出。设 \(f_S = \sum\limits_{i \in S} a_i, g_S = \sum\limits_{N(\{x\}) \subseteq S} b_x\),那么第一问的答案是 \(M = \min\limits_S\{f_S - g_S + 1 \mid g_S > 0\}\)。\(g_S > 0\) 是因为 \(S = N(T)\) 要存在。

考虑第二问。

一个简单的想法是,枚举满足 \(f_S - g_S + 1 = M\) 的集合 \(S\),把 \(\binom{f_S}{M}\) 求和。但是这样会算重,因为所有满足 \(f_S - g_S + 1 = M\) 的集合 \(S\) 有重叠部分。

不妨枚举删除的点所在集合 \(S\),设 \(h_S\) 为在 \(S\) 中选 \(M\) 个点,并且每个在 \(S\) 中的球都至少被选一个。答案即 \(\sum\limits_{S} [\exists T \supseteq S, f_T - g_T + 1 = M] h_S\)。

\(d_S = [\exists T \supseteq S, f_T - g_T + 1 = M]\) 可以高维前缀和求得。问题还剩下求 \(h_S\)。

考虑容斥,枚举 \(P \subseteq S\),钦定属于 \(P\) 的球不能被选,其余任意,我们得到 \(h_S = \sum\limits_{P \subseteq S} (-1)^{|P|} \binom{f_S - f_P}{M} = \sum\limits_{P \subseteq S} (-1)^{|S| - |P|} \binom{f_P}{M}\)。这个也可以高维前缀和求,每添加一位就取相反数即可。

时间复杂度是 \(O(2^n n)\) 的。

code
// Problem: H - Cabbage Master
// Contest: AtCoder - AtCoder Beginner Contest 215
// URL: https://atcoder.jp/contests/abc215/tasks/abc215_h
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 10050;
const int maxm = 2000100;
const int N = 2000000;
const ll mod = 998244353;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, m, a[maxn], b[maxn], c[22][maxn], d[maxm], f[maxm], g[maxm], h[maxm];
ll fac[maxm], ifac[maxm];

inline void init() {
	fac[0] = 1;
	for (int i = 1; i <= N; ++i) {
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[N] = qpow(fac[N], mod - 2);
	for (int i = N - 1; ~i; --i) {
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
}

inline ll C(ll n, ll m) {
	if (n < m || n < 0 || m < 0) {
		return 0;
	} else {
		return fac[n] * ifac[m] % mod * ifac[n - m] % mod;
	}
}

void solve() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
	}
	for (int i = 1; i <= m; ++i) {
		scanf("%lld", &b[i]);
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			scanf("%lld", &c[i][j]);
		}
	}
	for (int i = 1; i <= m; ++i) {
		int S = 0;
		for (int j = 1; j <= n; ++j) {
			if (c[j][i]) {
				S |= (1 << (j - 1));
			}
		}
		g[S] += b[i];
	}
	for (int i = 0; i < n; ++i) {
		for (int S = 0; S < (1 << n); ++S) {
			if (S & (1 << i)) {
				g[S] += g[S ^ (1 << i)];
			}
		}
	}
	ll mn = 1e18;
	for (int S = 1; S < (1 << n); ++S) {
		for (int i = 1; i <= n; ++i) {
			if (S & (1 << (i - 1))) {
				f[S] += a[i];
			}
		}
		if (g[S]) {
			if (f[S] < g[S]) {
				puts("0 1");
				return;
			}
			mn = min(mn, f[S] - g[S] + 1);
		}
	}
	for (int S = 1; S < (1 << n); ++S) {
		h[S] = C(f[S], mn);
		if (f[S] - g[S] + 1 == mn) {
			d[S] = 1;
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int S = 0; S < (1 << n); ++S) {
			if (S & (1 << i)) {
				h[S] = (h[S] - h[S ^ (1 << i)] + mod) % mod;
				d[S ^ (1 << i)] += d[S];
			}
		}
	}
	ll ans = 0;
	for (int S = 1; S < (1 << n); ++S) {
		if (d[S]) {
			ans = (ans + h[S]) % mod;
		}
	}
	printf("%lld %lld\n", mn, ans);
}

int main() {
	init();
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,typedef,215,Beginner,limits,sum,maxm,subseteq,ll
From: https://www.cnblogs.com/zltzlt-blog/p/17479958.html

相关文章

  • AtCoder Regular Contest 141 C Bracket and Permutation
    洛谷传送门AtCoder传送门考虑给出\(S\),如何求\(P,Q\)。先考虑\(P\),那我们肯定想让\(P\)的每一项都尽量往前靠。设\([1,k]\)为合法括号串,\(S_{k+1}=\texttt{)}\),那\(P\)的前\(k\)项依次为\(1\simk\),第\(k+1\)项不能为\(k+1\)了,那找到\(k+1\)之......
  • AtCoder Beginner Contest 273(E)
    AtCoderBeginnerContest273(E)E(链式结构,思维)E题目大意就是原本有一个空的序列,我们后面会进行\(q\)次操作,每次操作我们都需要输出此时的序列的最后数字下面有几种操作\(ADD\)\(x\),代表在这在这个序列的最后面添加一个\(x\)\(DELETE\),代表如果此时的序列存在数字的话,......
  • AtCoder Beginner Contest 265 F Manhattan Cafe
    洛谷传送门AtCoder传送门考虑dp,\(f_{i,j,k}\)表示考虑到第\(i\)维,\(\sum\limits_{x=1}^i|p_x-r_x|=j,\sum\limits_{x=1}^i|q_x-r_x|=k\)的方案数。转移是容易的,枚举\(r_i\)即可,\(f_{i,j,k}=\sum\limits_rf_{i-1,j-|p_i-r|,k-|q_i-r|}......
  • Atcoder Beginner Contest 301
    A-OverallWinner题目大意A和T两人玩游戏,给定一串只由A和T组成的字符串,如果第i个字符是A,则A赢得第i轮的胜利,反之则T赢;当遍历完整个字符串后,谁赢的轮数多谁就是最终赢家,如果一样则谁最先达到该轮数谁赢,输出赢家的名字解题思路签到题不多嗦了神秘代码......
  • AtCoder Beginner Contest 278 ABCDE
    AtCoderBeginnerContest278A-ShiftProblemStatement题意:给你一个长度为n的序列,让你移走前面k个后面补k个0。Solution思路:按照题意模拟即可。#include<bits/stdc++.h>usingnamespacestd;inta[1100];intmain(){ intn,k; cin>>n>>k; k=min(k,n); for(int......
  • UNIQUE VISION Programming Contest 2023 New Year (AtCoder Beginner Contest 287) A
    UNIQUEVISIONProgrammingContest2023NewYear(AtCoderBeginnerContest287)A-MajorityProblemStatement题意:给你n个字符串,字符串是For表示agree,字符串Against表示disagree,让你判断最终是否通过。Solution思路:统计For和Against的数量,比较一下即可。#include......
  • AtCoder Beginner Contest 284 ABCDE
    AtCoderBeginnerContest284A-SequenceofStringsProblemStatement题意:给你n个字符串,让你倒序输出Solve#include<bits/stdc++.h>usingnamespacestd;constintN=20;strings[N];intmain(){ intn; cin>>n; for(inti=1;i<=n;i++) cin>>s......
  • Atcoder-AGC033C
    看到这道题,是个博弈论,没见过树上的,于是想到在数列里的博弈论,又联想到树的特殊形式————链。于是我们来讨论一下链的情况(对于没有硬币的点,我们就视为它被删掉了):讨论链的情况发现若是选择两端的点,顶点数会减一;若是选择中间的点,顶点数会减二。现在我们站在链的角度来思考......
  • AtCoder Beginner Contest 302
    A-Attack题目大意给定两个数a和b,问我们需要进行多少次a-b,才能让a小于等于0解题思路签到题不多嗦了神秘代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e6+10;signedmain(){inta,b,c;cin>>a>>b;if(a%b......
  • AtCoder Beginner Contest 305 题解
    https://atcoder.jp/contests/abc305/tasks_printE-ArtGalleryonGraph冷知识:md这题赛时没做出来/cy刚看到题:这是什么题啊,\(K,h\)都\(1e5\)能做吗/fn确实能做。考虑类似SPFA的操作。设\(a_x\)表示\(x\)还可以对距离最多为\(a_x\)的点产生贡献,然后就直接......