Atcoder abc231
https://atcoder.jp/contests/abc231/tasks
G - Balls in Boxes
n个盒子, 初始第i个盒子有ai个球
k次操作
每次 等概率选一个盒子, 增加1个球
分数 = 最终每个盒子的球的个数之乘积
求分数期望 mod 998244353
范围
n 1000
k 1e9
ai [0, 1e9]
2s
1024 mb
我的思路
感觉上可以 做n和n-1的关系, 然后直接算频次, 最后除总次数 转成概率
F(n,k) = 前n个所有方案的乘积和, Ans = F(n,k) / n^k
对于最后一个盒子, 选择了j次, 对应的方案乘积和为 C(k,j) * F(n-1,k-j) * (a[n]+j)
F(n,k) = sum (a[n]+j) * F(n-1,k-j) * C(k,j), j=0..k
这里n虽然小, 但是k很大, 上面这个显然TLE, 如果能搞到n^2 左右的就好了
C(k,j) 的部分拆出来 分配给F的分母可以简化,但是依然没有去掉k的维度
题解
$E\lbrack \prod_i(A_i+X_i) \rbrack$
$E\lbrack(A_1+X_1)(A_2+X_2)\rbrack = E\lbrack A_1A_2\rbrack + E\lbrack A_1X_2\rbrack + E\lbrack X_1A_2\rbrack+ E\lbrack X_1X_2\rbrack$
$E\left[\prod_{i=1}^{N} (A_i+X_i)\right]=\sum_{n=0}^{N}S_{N,n}(A_1,\ldots,A_N)E\left[\prod_{i=1}^{N-n}X_i\right],$
$S_{N,n} $是从传入的$N$个中取n个的所有方案
$dp[i][j] = S_{i,j} (A_1\cdots A_i)$
考虑第$i+1$个是否选择有转义 $dp[i+1][j] = dp[i][j] + dp[i][j-1]A_{i+1}$
暴力n^2就好
当第j次操作选择第i个盒子 $X_{i,j} = 1$, 否则$X_{i,j} = 0$
$E\left[\prod_{i=1}^{n}X_i\right] = E\left[\prod_{i=1}^{n} \sum_{j=1}^{K}X_{i,j} \right]=\sum_{j_1,\ldots,j_n}E\left[\prod_{i=1}^{n}X_{i,j_i}\right].$, 先展开$X_i$ , 再像上面乘法分配展开,和期望展开
对于右侧$j_i$ 要两两不同则期望为$(\frac{1}{N})^n$, 否则为$0$(不能第j次 选多个盒子)
因此为排列数, $A(K,n)$,
暴力算
代码
https://atcoder.jp/contests/abc231/submissions/34624129
1 |
|
H - Minimum Coloring
h行,w列 矩阵
N个白色格子, 坐标分别(Ai,Bi), 需要代价Ci 让第i个变成黑色
求 让每行每列至少一个黑色的最小代价
保证至少有方案
范围
h,w 1e3
n 1e3
ci [1,1e9]
2s
1024mb
我的思路
感觉之前做过类似的, 像是网络流 最小割
整体思路是 把所有贡献变成正, 然后对源和汇分别定义 选还是不选, 然后用最小割对图的划分 有意义 选的代价 和 不选的代价
但是这里, 选的代价很好表示, 但不选的代价(全部不选则无限大代价) 不知道如何用点表示
即使拖出一个行节点, 倒是可以表示和S,T的边关系了, 却不知道怎么表示Pi,j和Rowi的关系
题解
图G
点, X_i 对应行 Y_j 对应列
边就是$(X_i,Y_j)$, 代价是$C_{i,j}$
求最小加权边覆盖(选边, 让所有点至少被选择一次)
直观地考虑“我们可以减少多少成本,而不是‘在每一行和每个顶点中选择成本最低的一块
- 随机选择边集E的子集$E_1$
- 对于每个不被$E_1$覆盖的点v, 选择一个v相连的最小代价的边, 允许重复选重复代价, E2 = E1 + 这些边, (注意到这些边又E_1唯一决定
虽然说可能 答案的边集不包含任何最小代价边,(1-3(2),1-4(1),2-4(2)) 但是第一步可能直接就得到答案
同时,在最优解中, 第一步的边不会有两边选了同一个点!!!
证明: 比如 a-b, a-c, 那么如果a-b 是b的最小边, 删掉a-b 结果不会更小,如果a-b不是b的最小边, 那么去掉a-b, 去选b的最小边, 得到更小的值 但是不小的点集, 因此去选都可以先不选, 得证
令$V_1$ 为$E_1$覆盖了的点集
令$v$的最小代价边权为$C_v$, 那么对于
$cost(E_2) = cost(E1) + \sum_{v \in V\setminus V_1} C_v$
$cost(E_2) = cost(E1) + \sum_{v \in V} C_v - \sum_{v \in V_1} C_v$
定义$c(e) = cost(e) - C_{e_u} - C_{e_v}$, $c(e)=$ 边代价 减去两点的最小权
$cost(E_2) = cost(E1) + \sum_{v \in V} c(e)$
而 第一个是定值, 那么就是要最小化第二个值
然后用 最小费用流
建图
$S \to X_i$ 容量1,单位代价0
对于每个$(X_i,Y_j)$, 边$X_i \to Y_j$ 容量1,单位代价 $c((X_i,Y_j)$, 因为不选就是0, 因此非负的边不要加
$Y_i \to T$ 容量1,单位代价0
任意流量的最小费用就是答案
注意MCMF不要负边权, 因此, 让所有流的单位费用增加 BIG = MAX(-c)
$S \to X_i$ 容量1,单位代价0
对于每个$(X_i,Y_j)$, 边$X_i \to Y_j$ 容量1,单位代价 $c((X_i,Y_j) + $
$Y_i \to T$ 容量1,单位代价0
变成 $= min(Cost_i - i*BIG)$, 其中i为流量
还可以用atcoder的库mcf_graph 的slope(S,T) -> std::vector<std::pair<Cap, Cost>>
得到 不同流量(注意到这里只需要关注斜率变化的点)对应的最小代价, 相当于一个凹函数被一个一次函数切
代码
https://atcoder.jp/contests/abc231/submissions/34624860
1 |
|
总结
G
概率论完全不会.. 忘记了哪些可以乘法加法, 啥变化规律 都忘了,
但其实也可以从积分/离散的期望定义来看, 不就是 int p(f(x)+g(x)) dx, = int p f(x) dx + int p g(x) dx, 所以加法是可拆的
这里虽然加了以后每个位置互不相同,但是如果把加的部分单独拎出来看, 就没有不同, 所以其实这里第一步做的期望拆分, 也就是把原来就有的ai和操作中对第i个增加的xi拆开来算
H
网络流会了一点, 但一点不会, 图论完全不会
这个神奇的边覆盖,图匹配 = min(随机(不重点的边) + 未选点的最小边集)
然后就是费用流的一种使用吧, 以及atcoder 提供的mcf和slope方法