[ZJOI2019] 开关 (一种扩展性较高的做法)

题意:

有n个开关,一开始状态都为关闭。每次随机选出一个开关将其状态改变,选出第i个开关的概率为${ p_i \over \sum_{i=1}^n p_i} $,求状态第一次变为s的操作步数。

题解:

考虑先从组合方法入手。
最基本的思路就是枚举一种必定结束的状态,但是这样的状态不一定合法,因为这个状态的前缀可能已经结束了,所以我们可以容斥若干个前缀,强制这些前缀已经结束,来算出这个状态中没有一个前缀能够结束的方案数。
当然,在枚举的过程中,"一种状态"可以通过枚举每一个开关的操作次数\(x_i\),再将这些操作次数排列起来,我们枚举前缀的时候,同样枚举每个开关的操作次数,那么我们可以写出答案的式子:
\[\sum_{x_i} \prod [2|x_i-s_i] \prod q_i^{x_i} \sum_{i=1}^nx_i \sum_{m=0}^{\infty} \sum_{y_{1i};\exists i,y_{1i}>0 } \sum_{y_{2i};\exists i,y_{2i}>0 }... \sum_{y_{mi};\exists i, y_{mi}>0 } \sum_{{z_i};\exists i,z_i>0 }\\
\prod [2|y_{ij}] \prod_{j}[\sum_{i=1}^m y_{ij} +z_i = x_i] (-1)^m {(\sum_{i=1}^m z_i)! \over \prod_{i=1}^n z_i!}\prod_{i=1}^m {(\sum_{j=1}^n y_{ij})! \over \prod_{j=1}^n y_{ij}} \]
\(q_i\)为\(p_i \over \sum p_i\)

看起来十分复杂,其实有很多可以化简的地方,为了保证题解的简洁性,这里不一一赘述。上述式子最难化简的莫过于是\(\sum x_i\),这个其实是一个带权方案数,在算的时候我们可以认为是计算$[y^1]\prod_{i=1}^n (1+x_iy) $,所以只需要记常数项与一次项系数。

用指数型生成函数来表示,可以方便的得到答案式子:
\[F(x)=\prod (e^{q_ix} + q_ixye^{q_ix} +(-1)^{s_i} e^{-q_ix} - (-1)^{s_i} q_i xye^{-q_ix}) \\ =\sum_{i=0}^{\infty} {f_{0i} \over i!}x^i + {f_{1i} \over i!}x^iy\]

\[G(x)=\prod (e^{q_ix} + q_ixye^{q_ix} + e^{-q_ix} - q_i xye^{-q_ix}) \\
=\sum_{i=0}^{\infty}{g_{0i} \over i!}x^i + {g_{1i} \over i!}x^iy\]

记\(f_0(x)=\sum_{i=0}^{\infty}f_{0i}x^i,f_1(x)=\sum_{i=0}^{\infty}f_{1i}x^i,f(x)=f_0(x)+f_1(x)y\)
\(g_0(x)=\sum_{i=0}^{\infty}g_{0i} x^i,g_1(x)=\sum_{i=0}^{\infty}g_{1i}x^i,g(x)=g_0(x)+g_1(x)y\)
以\(F(x)\)为例,\(F(x)=\sum_{i=- \infty}^{\infty} a_i e^{ix} + b_i xy e^{ix}\)
可以得到\(f(x)=\sum_{i=- \infty}^{\infty} {a_i \over 1-ix}+{b_i x\over (1-ix)^2}\)
答案为
\[\lim_{x \to 1 }[y^1]f(x)\sum_{m=0}^{\infty}(-g(x)+1)^m=\lim_{x \to 1}[y^1]{f(x) \over g(x)}\\
={f_2(x)g_1(x) -g_2(x)f_1(x) \over g_1^2(x)}\]
我们发现在\(g_1(x)\)中有\(\frac {1} {1-x}\)的项,在\(f_2(x),g_2(x)\)有\(\frac {1} {(1-x)^2}\)的项,所以我们发现,答案的分子有三阶无穷大的项,分母有二阶无穷大的项。
那么是否意味着答案发散呢?恰恰相反,因为感性理解答案肯定是收敛的,所以我们有理由认为分子上三阶无穷大的系数为0,而事实也确实如此,因为\(f_2(x)与g_2(x)\)的\(1 \over (1-x)^2\)项系数相同,\(f_1(x)与g_1(x)\)的\(1 \over 1-x\)项的系数也相同,我们计算答案,只需要计算分子的二阶无穷大的值除以分母的二阶无穷大的值即可,又因为两个无穷大都为\({1\over (1-x)^2}\),所以是可以约去的。

这种做法与网上的大致相同,但是在处理\(\sum x_i\)项的时候不太一样,网上题解大多是用的求导来解决第i项对答案的贡献为i的问题,而本文观察到了\(\sum x_i = [y^1]\prod (1+x_iy)\)的性质。这种做法无疑具有比较高的扩展性,例如操作开关i需要\(a_i\)的代价,求代价的期望,求导方法便显得十分无力,而这个方法只需要将原式稍稍更改成\(\sum a_i x_i = [y^1]\prod (1+a_ix_iy)\)即可。
code

[ZJOI2019] 开关 (一种扩展性较高的做法)的更多相关文章

  1. 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  2. Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结

    Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结 1. 什么是可扩展的应用程序?1 2. 松耦合(ioc)2 3. 接口的思考 2 4. 单一用途&模块化,小粒度化2 ...

  3. 优秀开源项目之三:高性能、高并发、高扩展性和可读性的网络服务器架构State Threads

    译文在后面. State Threads for Internet Applications Introduction State Threads is an application library ...

  4. jetbrick,新一代 Java 模板引擎,具有高性能和高扩展性

    新一代 Java 模板引擎,具有高性能和高扩展性. <!-- Jetbrick Template Engineer --> <dependency> <groupId&g ...

  5. TCP接入层的负载均衡、高可用、扩展性架构

    一.web-server的负载均衡 互联网架构中,web-server接入一般使用nginx来做反向代理,实施负载均衡.整个架构分三层: 上游调用层,一般是browser或者APP 中间反向代理层,n ...

  6. (转)mysql数据库高可用高扩展性架构方案实施

    http://shanhu.blog.51cto.com/1293405/1212605-----mysql数据库高可用高扩展性架构方案实施

  7. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  8. 【Java/Android性能优5】 Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/android-imagecache/ 主要介绍一个支持图片自动预取.支持多种缓存算法.支持二级缓存.支持数据保存和恢复的图片缓存的 ...

  9. 深入NGINX:我们如何设计它的性能和扩展性

    为了更好地理解设计,你需要了解NGINX是如何工作的.NGINX之所以能在性能上如此优越,是由于其背后的设计.许多web服务器和应用服务器使用简单的线程的(threaded).或基于流程的 (proc ...

随机推荐

  1. Paper | Residual Attention Network for Image Classification

    目录 1. 相关工作 2. Residual Attention Network 2.1 Attention残差学习 2.2 自上而下和自下而上 2.3 正则化Attention 最近看了些关于att ...

  2. js input radio点击事件

    html代码: <input type="radio" name="myname" value="1" />1 <inpu ...

  3. Google工作法

    本文转自:https://www.yuque.com/heqingbao/msfy2c/zg56gm 这几天去上海参加Google开发者大会,利用空闲时间读了一本快餐书,书名叫<Google工作 ...

  4. 详解JAVA8Stream 方法引用(基础){全}

    1: Stream流 1.1 引言 1.2 流式思想概述 1.3 获取流 1.4 常用方法 1.5 练习:集合元素处理 2:方法引用 2.1 冗余的Lambda场景 2.2 方法引用符 2.3 通过对 ...

  5. 转载:ubuntu下编译安装nginx及注册服务

    原文地址:https://www.cnblogs.com/EasonJim/p/7806879.html 安装gcc g++的依赖库 sudo apt-get install build-essent ...

  6. win10启动telnet

    1.点击win菜单,点击设置图标 2.选择系统选项 3.选择应用与程序选项 4.拉到最下方,选择程序与功能 5.选择启用或关闭windows功能 6.下拉找到telnet客户端选项勾选

  7. [ida]查看某一函数在程序中被谁引用

    1. 点亮函数名 2.view - open subviews - cross references 注意:不要点击绘图那个

  8. 如何使用npm的部分用法以及npm被墙的解决方法

    我们要明白我们使用的npm就是node中自带的包(模块)管理工具:借助NPM可以帮助我们快速安和管理依赖包,使Node与第三方模块之间形成了一个良好的生态系统. 我们可以直接输入npm,查看帮助引导: ...

  9. vueInitVux中引入bootstrap、jquery步骤

    1.先从github上下载 vueInitVux 2.将 build下webpack.base.conf.js 文件 替换成 Html5IQ下的文件 3.npm i 4.npm i jquery -- ...

  10. 前端开发工具HBuilder使用技巧以及快捷键

    创建HTML结构: h 8 (敲h激活代码块列表,按8选择第8个项目,即HTML代码块,或者敲h t Enter) 中途换行: 'Ctrl+Enter' 设置charset: m e 6 Enter ...