\(\mathcal{Description}\)

  Link.

  给定非负整数序列 \(\{a_n\}\) 和 \(m\),每次随机在 \(\{a\}\) 中取一个非零的 \(a_i\)(保证存在),令其 \(-1\),重复 \(m\) 次,求最终 \(\{a\}\) 中 \(0\) 的期望个数。

  \(n\le15\),\(m\le100\)。

\(\mathcal{Solution}\)

  既然有 DP of DP,我觉得这种题就叫 DP and DP。(

  看到 \(n\le15\),想要状压,但无论如何都不能完整记录 \(\{a\}\) 的状态,也就不可能及时知道某个 \(a\) 会否变成 \(0\),怎么办呢?

  既然不知道,我们索性不去动它们——设前 \(i\) 次操作后,\(\{a\}\) 中为 \(0\) 的下标集合为 \(S\), 我们只落实对 \(S\) 中元素造成影响的操作,共 \(\sum_{i\in S}a_i\) 次;而对于剩下 \(\left(i-\sum_{i\in S}a_i\right)\) 次,只记录为“它们会影响某个不在 \(T\) 中元素”,其中 \(T\) 是进行这个操作时的 \(0\) 值集合;“某个”是具体的,但尚未确定的一个,所以提供概率 \(\frac{1}{n-|T|}\)。另一方面,只有在扩充 \(S\) 时来确定若干“某个”,此时就只需要组合选取,而不需要乘概率了。那么摆出式子,令 \(f(i,S)\) 表示 \(i\) 次操作后,\(0\) 值集合为 \(S\) 的概率(概率计算方式如前文),则:

\[f(i,S)=\frac{1}{n-|S|}f(i-1,S)+\frac{1}{n-|S|+1}\sum_{j\in S}\binom{i-1-\sum_{k\in S,k\not= j}a_k}{a_j-1}f(i-1,S\setminus\{j\}).
\]

  思考此时得到的,应该用于计算答案的 \(f(m,S)\) 意味什么:落在 \(S\) 内的操作,它们是正常的,而其余的 \(\left(m-\sum_{i\in S}a_i\right)\) 次,它们一定落在 \(U\setminus S\)(\(U\) 为全集)中,遗漏的仅仅是方案数!所以在 \(f\) 的目标状态为基础,再来一个 DP:令 \(g(i,S)\) 表示有 \(i\) 次操作落在 \(S\),且 \(S\) 中不存在 \(0\) 值的方案数,简单地,任取一个 \(x\in S\),得到转移:

\[g(i,S)=\sum_{j=0}^{\min\{i,a_{x}-1\}}\binom{i}{j}g(i-j,S\setminus\{x\}).
\]

最终答案则为:

\[\sum_{S\subseteq U}f(m,S)\cdot g(m-\sum_{i\in S}a_i,U\setminus S)\cdot|S|.
\]

  复杂度为 \(\mathcal O(m(n+m)2^n)\)。

\(\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 int imin( const int a, const int b ) { return a < b ? a : b; } typedef long double LD;
#define double LD const int MAXN = 15, MAXM = 100;
int n, m, a[MAXN + 5], sum[1 << MAXN], bitc[1 << MAXN], bitw[1 << MAXN];
double comb[MAXM + 5][MAXM + 5], f[2][1 << MAXN], g[MAXM + 5][1 << MAXN]; inline void init() {
comb[0][0] = 1.;
rep ( i, 1, m ) {
comb[i][0] = 1.;
rep ( j, 1, i ) comb[i][j] = comb[i - 1][j] + comb[i - 1][j - 1];
}
} inline void getF() {
f[0][0] = 1.;
rep ( i, 1, ( 1 << n ) - 1 ) bitc[i] = bitc[i ^ ( i & -i )] + 1;
for ( int i = 1, sta = 1; i <= m; ++i, sta ^= 1 ) {
rep ( S, 0, ( 1 << n ) - 1 ) {
f[sta][S] = 0.;
rep ( j, 0, n - 1 ) if ( S >> j & 1 ) {
f[sta][S] += i < sum[S ^ 1 << j] + 1 ? 0 :
comb[i - sum[S ^ 1 << j] - 1][a[j] - 1] * f[!sta][S ^ 1 <<j];
}
f[sta][S] /= n - bitc[S] + 1;
if ( n > bitc[S] ) f[sta][S] += f[!sta][S] / ( n - bitc[S] );
// fprintf( stderr, "f(%d,%d)=%f\n", i, S, f[sta][S] );
}
}
} inline void getG() {
rep ( i, 2, ( 1 << n ) - 1 ) bitw[i] = bitw[i >> 1] + 1;
rep ( S, 0, ( 1 << n ) - 1 ) g[0][S] = 1.;
rep ( i, 1, m ) {
rep ( S, 1, ( 1 << n ) - 1 ) {
int v = bitw[S & -S]; double &cur = g[i][S];
rep ( j, 0, imin( i, a[v] - 1 ) ) {
cur += g[i - j][S ^ 1 << v] * comb[i][j];
}
// fprintf( stderr, "g(%d,%d)=%.0f\n", i, S, g[i][S] );
}
}
} int main() {
scanf( "%d %d", &n, &m ), init();
rep ( i, 0, n - 1 ) scanf( "%d", &a[i] ), sum[1 << i] = a[i];
rep ( S, 1, ( 1 << n ) - 1 ) sum[S] = sum[S & -S] + sum[S ^ ( S & -S )]; getF(), getG(); double ans = 0.;
rep ( S, 0, ( 1 << n ) - 1 ) if ( m >= sum[S] ) {
ans += f[m & 1][S] * g[m - sum[S]][repS ^ S] * bitc[S];
}
printf( "%.12Lf\n", ans );
return 0;
}

Solution -「Gym 102798E」So Many Possibilities...的更多相关文章

  1. Solution -「Gym 102979E」Expected Distance

    \(\mathcal{Description}\)   Link.   用给定的 \(\{a_{n-1}\},\{c_n\}\) 生成一棵含有 \(n\) 个点的树,其中 \(u\) 连向 \([1, ...

  2. Solution -「Gym 102979L」 Lights On The Road

    \(\mathcal{Description}\)   Link.   给定序列 \(\{w_n\}\),选择 \(i\) 位置的代价为 \(w_i\),要求每个位置要不被选择,要不左右两个位置至少被 ...

  3. Solution -「Gym 102956F」Find the XOR

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \(m\) 条边的连通无向图 \(G\),边有边权.其中 \(u,v\) 的距离 \(d(u,v)\) ...

  4. Solution -「Gym 102956B」Beautiful Sequence Unraveling

    \(\mathcal{Description}\)   Link.   求长度为 \(n\),值域为 \([1,m]\) 的整数序列 \(\lang a_n\rang\) 的个数,满足 \(\not\ ...

  5. Solution -「Gym 102956F」Border Similarity Undertaking

    \(\mathcal{Description}\)   Link.   给定一张 \(n\times m\) 的表格,每个格子上写有一个小写字母.求其中长宽至少为 \(2\),且边界格子上字母相同的矩 ...

  6. Solution -「Gym 102956A」Belarusian State University

    \(\mathcal{Description}\)   Link.   给定两个不超过 \(2^n-1\) 次的多项式 \(A,B\),对于第 \(i\in[0,n)\) 个二进制位,定义任意一个二元 ...

  7. Solution -「Gym 102798I」Sean the Cuber

    \(\mathcal{Description}\)   Link.   给定两个可还原的二阶魔方,求从其中一个状态拧到另一个状态的最小步数.   数据组数 \(T\le2.5\times10^5\). ...

  8. Solution -「Gym 102798K」Tree Tweaking

    \(\mathcal{Description}\)   Link.   给定排列 \(\{p_n\}\),求任意重排 \(p_{l..r}\) 的元素后,将 \(\{p_n\}\) 依次插入二叉搜索树 ...

  9. Solution -「Gym 102759I」Query On A Tree 17

    \(\mathcal{Description}\)   Link.   给定一棵含 \(n\) 个结点的树,结点 \(1\) 为根,点 \(u\) 初始有点权 \(a_u=0\),维护 \(q\) 次 ...

随机推荐

  1. spring cloud feign 报错 feign.FeignException$MethodNotAllowed: status 405 reading 解决

    1.前言 出现报错 feign.FeignException$MethodNotAllowed: status 405 reading XXXXX 需要检查 接口的请求参数是否一致 请求参数是否正确添 ...

  2. ubuntu 18.04 检测到系统程序出现问题

    检测到系统程序出现问题,想立即报告这个问题吗? 可以暂时先把这个提示关闭掉 $ sudo vi /etc/default/apport 找到第4行 修改为 enabled=0 保存退出 附linux中 ...

  3. react将HTML字符串解析为HTML标签

    当后台返回的数据是字符串html的话,我们可以利用dangerouslySetInnerHTML属性来把字符串转换成html标签 function showhtml(htmlString){ var ...

  4. Hive的分析函数的使用

    原文: https://www.toutiao.com/i6769120000578945544/?group_id=6769120000578945544 我们先准备数据库.表和数据 开窗分析函数相 ...

  5. Jenkins Hackfest 用户体验文档报告

    Jenkins 技术文档是我们项目的重要组成部分,因为它是正确使用 Jenkins 的关键.好的文档可以指导用户,并鼓励选择好的实现方式.这是用户体验的关键部分.在最近的 Jenkins UI/UX ...

  6. gopher协议在SSRF漏洞中的作用

    1.什么是gopher协议?2.如何使用gopher协议反弹shell?3.在SSRF中如何使用gopher协议反弹shell? 一.什么是gopher协议?定义:Gopher是Internet上一个 ...

  7. 《Flink SQL任务自动生成与提交》后续:修改flink源码实现kafka connector BatchMode

    目录 问题 思路 kafka参数问题 支持batchmode的问题 参数提交至kafkasource的问题 group by支持问题 实现 编译 测试 因为在一篇博文上看到介绍"汽车之家介绍 ...

  8. 【Java】泛型

    文章目录 泛型 为什么要有泛型 在集合中使用泛型 如何自定义泛型结构 自定义泛型类.接口 泛型方法 泛型在继承方面的体现 通配符的使用 有限制条件的通配符的使用 泛型 为什么要有泛型 集合容器类在设计 ...

  9. 【C++】指针和函数

    指针和函数 标签:c++ 目录 指针和函数 一.基本概念 定义: 指针的定义及使用: 二.指针的相互赋值 三.指针的运算 比较大小: 相减: 加减整数类型变量或者常量: 自增自减: 下标运算符[ ]: ...

  10. 【刷题-LeetCode】210. Course Schedule II

    Course Schedule II There are a total of n courses you have to take, labeled from 0 to n-1. Some cour ...