ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】ABC231G - Balls in Boxes & H - Minimum Coloring

2021-12-16 17:00:21  阅读:185  来源: 互联网

标签:Balls rp int 题解 rep read Boxes ans sum


G 想到一个非常神奇的做法。

如果我们令第 \(i\) 个位置放入了 \(b_i\) 个球,那么总代价一定是 \(\prod(a_i + b_i)\)。

总方案数是 \(n^k\),我们只用求所有方案的代价之和。

对于一个代价,我们将它拆开,组合意义等价于选出一些 \(a_i\),剩下的选 \(b_i\),乘起来然后求和。

由于 \(a\) 是固定的,我们先简单 DP 一下求得 \(f_{n,i}\) 表示从 \(n\) 个数中,选出 \(i\) 个数的乘积的和,直接做是 \(\mathcal{O}(N^2)\) 已经足够了。

接下来我们枚举选出了 $x $ 个 \(b_i\),它们的和为 \(s(s\le k)\)。

那么答案为 \(\sum\limits_{x = 0}^n f_{n, x}\sum\limits_{s = 0}^k \binom{k}{s}(n - x)^{k - s}g_{x, s}\)。

其中 \(g_{n, k}\) 表示有 \(n\) 个空盒子,进行 \(k\) 次操作,所有情况的代价之和。

显然 \(g_{1, k} = k\), \(g_{n,k} = \sum\limits_{i = 0}^{k}i\binom{k}{i}g_{n - 1,k -i}\)。经过递推和组合恒等变换后可以求得 \(g_{n,k} = \dfrac{k!n^{k - n}}{(k - n)!}\)。

(这个式子可以在变形后归纳证明,不知道有没有简单的组合意义解法

我们将这个式子带回去,可以求得 \(\sum\limits_{s = 0}^k \binom{k}{s}(n - x)^{k - s}g_{x, s} = \dfrac{k!n^{k - x}}{(k - x)!}\)。

这式子可以直接 \(\mathcal{O}(N)\) 求,时间复杂度 \(\mathcal{O}(N^2)\)。

#define N 1005
int n, a[N], f[N][N], k;
int g(int x){
	int cur = Pow(n, k - x);
	rep(i, 1, x)cur = 1LL * cur * (k - i + 1) % P;
	return cur;
}
int main(){
	n = read(), k = read();
	rep(i, 1, n)a[i] = read();
	f[0][0] = 1;
	rep(i, 1, n)rep(j, 0, n - 1)
		ad(f[i][j], f[i - 1][j]), ad(f[i][j + 1], f[i - 1][j] * 1LL * a[i] % P);
	int ans = 0;
	rep(i, 0, n)ad(ans, g(i) * 1LL * f[n][n - i] % P);
	ans = 1LL * ans * Pow(n, -k) % P;
	printf("%d\n", ans);
	return 0;
}

H 题很有意思,可惜没想出来。

显然这个个行列二分图模型,对于一个可以染色的格子对应一条权值为 \(c_i\) 的边,然后求二分图的带权最小边覆盖。

大家只知道最小边覆盖可以直接求最大匹配,考虑扩展到带权图。

对于最有情况,我们将选择的边扣出来,然后对这个边集的生成子图跑出最大匹配,显然不在匹配中的点,它也要被覆盖,它一定会选择相邻的最小的边去覆盖它。

所以对于每个点我们求相邻的边的最小值 \(v_i\),对于一个格子 \((a,b,c)\),连一条行 \(a\) 到列 \(b\), 权值为容量为 \(1\),权值为 \(v_a+v_b-c\) 的边,然后跑最大费用流即可。答案就是最大 \(\sum v - ans\)。

注意这里的最大费用流是指费用最大的可行流而不是最大流,由于每条边容量最大为 \(1\),我们只增广代价为正的路径即可。

感觉这个模型非常类似反悔贪心,不知道能不能扩展。

#define N 2005
#define int long long
int n, m, T, a[N], b[N], c[N], h[N], tot = 1, u[N];
struct edge{int to, nxt, val, cap;}e[N << 5];
void add(int x,int y,int z,int val){
	e[++tot].nxt = h[x], h[x] = tot, e[tot].to = y, e[tot].cap = z, e[tot].val = val;
	e[++tot].nxt = h[y], h[y] = tot, e[tot].to = x, e[tot].cap = 0, e[tot].val = -val;
}
int flow[N], pre[N], d[N], v[N], s, t, ans;
queue<int>q;
bool bfs(){
	memset(d, 0xcf, sizeof(d));
	q.push(s), d[s] = flow[t] = 0, flow[s] = 1;
	while(!q.empty()){
		int x = q.front();
		q.pop(), v[x] = 0;
		for(int i = h[x]; i; i = e[i].nxt)if(e[i].cap && d[x] + e[i].val > d[e[i].to]){
			d[e[i].to] = d[x] + e[i].val, flow[e[i].to] = 1, pre[e[i].to] = i;
			v[e[i].to] = 1, q.push(e[i].to);
		}
	}
	return d[t] > 0;
}
void updata(){
	ans -= d[t];
	int x = t;
	while(x != s){
		e[pre[x]].cap --;
		e[pre[x] ^ 1].cap ++;
		x = e[pre[x] ^ 1].to;
	} 
}
signed main(){
	n = read(), m = read(), T = read();
	memset(u, 0x3f, sizeof(u));
	rp(i, T){
		a[i] = read(), b[i] = read(), c[i] = read();
		cmn(u[a[i]], c[i]), cmn(u[b[i] + n], c[i]);
	}
	s = n + m + 1, t = s + 1;
	rp(i, n)add(s, i, 1, 0);
	rp(i, m)add(i + n, t, 1, 0);
	rp(i, n + m)ans += u[i];
	rp(i, T)add(a[i], b[i] + n, 1, u[a[i]] + u[b[i] + n] - c[i]);
	while(bfs())updata();
	printf("%lld\n", ans);
	return 0;
}

标签:Balls,rp,int,题解,rep,read,Boxes,ans,sum
来源: https://www.cnblogs.com/SharpnessV/p/15698997.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有