\(\rm upd\):是我假了...这题没有爆精...大家要记得这道题是相对误差\(10^{-6}\)...感谢@foreverlasting的指正。

题是好题,可是标算爆精是怎么回事...要写的和标算一毛一样才能过。

各位要写的话过了前5个点就当过了吧...

题意

你有\(n\)张牌,每张牌上有一个\(1\sim m\)的点数,你每次随机选出两张不同的牌\(A\)和\(B\),并将\(A\)的点数变为\(B\)的点数。求将所有牌的点数变成一样的期望步数。用\(double\)输出。\(n\leq 10^9\),\(m\leq 10^5\)。

题解

那首先有个挺显然的想法是枚举最终变成了哪种牌,那么所有牌就变成了是这种牌与不是这种牌两类。我们这么计算这种情况的贡献:

假如若干步以后,是这种牌的数量变为\(0\),则这种情况的贡献为\(0\)。
否则,若干步以后是这种牌的数量变为\(n\),则这种情况的贡献为\(发生的概率*步数\)。

那么只要把每种牌的这个答案加起来就好了。

现在我们要解决的问题是:有两种牌,第一种有\(i\)张,第二种有\(n-i\)张,问最终全变为第一种牌的贡献。

很显然当\(n\)固定的时候,答案只和\(i\)有关。于是我们将其记为\(f_i\)。

在计算\(f_i\)之前,我们先来计算辅助数组\(g\)。其中\(g_i\)表示有两种牌,第一种有\(i\)张,第二种有\(n-i\)张,问最终全变为第一种牌的概率

怎么求\(g_i\)呢?首先边界条件有\(g_0=0\),\(g_n=1\),再来考虑一般的情况。

我们来考虑一下第一次对牌数有影响的操作。假如\(A\)是第一种牌,\(B\)是第二种牌,那么第一种牌数\(-1\);假如\(A\)是第二种牌,\(B\)是第一种牌,那么第一种牌数\(+1\)。显然这两种情况的方案数是一样的,于是可以得出\(i\)会等概率变成\(i-1\)或\(i+1\),于是就可以得到一个简单的式子:

\[g_i=\frac{1}{2}(g_{i-1}+g_{i+1})\]

于是移项得到:

\[g_{i+1}=2*g_i-g_{i-1}\]

可以发现每一项都依赖前两项,于是我们设\(g_1=x\),则可计算出\(g_2=2*x\),\(g_3=3*x\),\(\dots\),那么显然我们可以猜想\(g_i=i*x\),可以通过归纳法证明其是成立的。

于是得到\(g_n=n*x=1\),解得\(x=\frac{1}{n}\)。

因此当第一种牌数为\(i\)时,最终全变成第一种牌的概率为\(\frac{i}{n}\)。

现在来考虑求\(f_i\),边界条件有\(f_0=0\),\(f_n=0\),一般情况显然还是可以归纳成\(f_{i-1}\)和\(f_{i+1}\)的情况。不过这次还要额外考虑一些事情:

以变成\(i-1\)为例,首先我们枚举在几步以后变成\(i-1\)。设没有影响的操作发生概率为\(p\),使\(i\)变为\(i-1\)的操作发生概率为\(q\)。则可得到期望额外花费的步数为:

\[\sum_{j\geq 0}\Big((j+1)*p^j*q\Big)\]

整理得其为\(\frac{q}{(1-p)^2}\)。

还要注意的是由于规约到\(i-1\)的情况后成功的概率是\(\frac{i-1}{n}\),而失败的贡献是\(0\),因此期望步数只有\(\frac{i-1}{n}\)是有效的,贡献为\(\frac{q}{(1-p)^2}*\frac{i-1}{n}\)。

对于\(i+1\)的情况,\(p\)和\(q\)是一样的,因此贡献为\(\frac{q}{(1-p)^2}*\frac{i+1}{n}\)。两者相加为\(\frac{q}{(1-p)^2}*\frac{2*i}{n}\)。

可以计算得\(1-p=\frac{2*i*(n-i)}{n*(n-1)}\),\(q=\frac{i*(n-i)}{n*(n-1)}\)。于是原式可化简为:

\[\frac{n-1}{2*(n-i)}\]

因此可以得到:

\[f_i=\frac{1}{2}(f_{i-1}+f_{i+1})+\frac{n-1}{2*(n-i)}\]

移项可得:

\[f_{i+1}=2*f_i-f_{i-1}-\frac{n-1}{n-i}\]

依然设\(f_1=x\),则\(f_2=2*x-\frac{n-1}{n-1}\),\(f_3=3*x-2*\frac{n-1}{n-1}-\frac{n-1}{n-2}\),\(\dots\),依然可以通过观察和归纳法证明:

\[f_i=i*x-\sum_{j=1}^{i-1}\Big((i-j)*\frac{n-1}{n-j}\Big)\]

那么对于\(f_n\):

\[f_n=n*x-\sum_{j=1}^{n-1}\Big((n-j)*\frac{n-1}{n-j}\Big)=0\]

可解得\(x=\frac{(n-1)*(n-1)}{n}\)。

于是继续对\(f_i\)的式子进行化简:

\[f_i=i*\frac{(n-1)*(n-1)}{n}-i*(n-1)*\Big(\sum_{j=1}^{i-1}\frac{1}{n-j}\Big)+(n-1)*\Big(\sum_{j=1}^{i-1}\frac{j}{n-j}\Big)\]

我们设\(H_i\)为调和数,即\(H_i=\sum_{j=1}^{i}\frac{1}{j}\),则第二项等于:

\[-i*(n-1)*(H_{n-1}-H_{n-i})\]

继续推导第三项:

\[(n-1)*\Big(\sum_{j=1}^{i-1}\frac{j}{n-j}\Big)\]

\[(n-1)*\Big(\sum_{j=1}^{i-1}\big(\frac{n}{n-j}-1\big)\Big)\]

\[(n-1)*n*\Big(\sum_{j=1}^{i-1}\frac{1}{n-j}\Big)-(n-1)*(i-1)\]

\[(n-1)*n*(H_{n-1}-H_{n-i})-(n-1)*(i-1)\]

将三项合并,最终得到:

\[f_i=i*\frac{(n-1)*(n-1)}{n}+(n-1)*(n-i)*(H_{n-1}-H_{n-i})-(n-1)*(i-1)\]

那么问题来了,\(n\)那么大,\(H_n\)怎么求呢?标算的做法是将小的调和数预处理,大的用\(H_x\simeq \ln x+\gamma\)来近似,其中\(\gamma\)为欧拉常数。但是不知道为啥标算的\(\gamma\)取的是\(0.57\)...不过实测下来就算预处理前\(2^{20}\)的调和数以及用较精确的欧拉常数后面的误差也在\(10^{-7}\)左右...再乘以一个大常数算答案精度堪忧。

这里再提供一个精度靠谱复杂度也有保证的做法。注意到答案中计算贡献的调和数其实类似于倒数的后缀和,因此\(i\)较小的时候显然可以预处理。可以设一个阈值\(T\),预处理前\(T\)个后缀和,剩下的数不会超过\(\frac{n}{T}\)个,可以用分段打表暴力处理。由于查询量不是很大,打表的间隔可以取大一点减少代码长度。

还有由于答案有点大最好开\(long\ double\)或者自己写精度更高的类型...不过反正标算都爆精了这些好像也是后话了。这么好的题为什么不取模呢,用第二种做法就很靠谱了。

LOJ#6118 鬼牌的更多相关文章

  1. [loj6118]鬼牌

    枚举最终所有牌的大小$i$,对于最终所有牌大小都为$i$的情况,令其贡献为步数,否则令其贡献为0,记$F$为期望贡献(即所有情况概率*贡献之和),答案即为$\sum_{i=1}^{m}F$ 显然,$F ...

  2. UOJ147 斗地主

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关 系根据牌的数码表示如下:3<4&l ...

  3. UOJ 151 斗地主“加强”版

    #151. [NOIP2015]斗地主“加强”版 统计 描述 提交 自定义测试 本题开放Hack 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54 ...

  4. FZU 2216 The Longest Straight(最长直道)

    Description 题目描述 ZB is playing a card game where the goal is to make straights. Each card in the dec ...

  5. Pandas python

    原文:  https://github.com/catalystfrank/Python4DataScience.CH   和大熊猫们(Pandas)一起游戏吧!   Pandas是Python的一个 ...

  6. Python数据分析入门之pandas基础总结

    Pandas--"大熊猫"基础 Series Series: pandas的长枪(数据表中的一列或一行,观测向量,一维数组...) Series1 = pd.Series(np.r ...

  7. 扑克牌(cards)

    扑克牌 思路 这题也是二分!! 我们二分有几套牌,然后再去检验是否符合,至于怎么想到的,不要问我,我也不知道 那么我们主要解决的就是check函数 我们将二分的套数和每种牌的数量进行比较,如果该种牌的 ...

  8. Codeforces 1392H - ZS Shuffles Cards(DP+打表找规律)

    Codeforces 题面传送门 & 洛谷题面传送门 真·两天前刚做过这场的 I 题,今天模拟赛就考了这场的 H 题,我怕不是预言带师 提供一种奇怪的做法,来自于同机房神仙们,该做法不需要 M ...

  9. Solution -「CF 1392H」ZS Shuffles Cards

    \(\mathcal{Description}\)   Link.   打乱的 \(n\) 张编号 \(1\sim n\) 的数字排和 \(m\) 张鬼牌.随机抽牌,若抽到数字,将数字加入集合 \(S ...

随机推荐

  1. 20155220 Exp5 MSF基础应用

    Exp5 MSF基础应用 一个主动攻击实践,MS08-067 首先利用msfconsole启用msf终端 然后利用search MS08-067搜索漏洞,会显示相应漏洞模块 根据上图,我们输入use ...

  2. EZ 2018 03 09 NOIP2018 模拟赛(三)

    最近挺久没写比赛类的blog了 链接:http://211.140.156.254:2333/contest/59 这次的题目主要考验的是爆搜+打表的能力 其实如果你上来就把所有题目都看过一次就可以知 ...

  3. 【Java框架型项目从入门到装逼】第十三节 用户新增功能完结篇

    这一节,我们把用户新增的功能继续做一个完善.首先,新增成功后,需要给前台返回一个信息,就是告诉浏览器,这次用户新增的操作到底是成功了呢,还是失败了呢?为此,我们需要专门引入一个结果类,里面只有两个属性 ...

  4. 【LG4070】[SDOI2016]生成魔咒

    [LG4070][SDOI2016]生成魔咒 题面 洛谷 题解 如果我们不用在线输的话,那么答案就是对于所有状态\(i\) \[ \sum (i.len-i.fa.len) \] 现在我们需要在线询问 ...

  5. libgdx相关知识点

    Gdx.graphics.setContinuousRendering(false); 设置图像为非连续自动渲染. 设置Opengl的混合模式,支持alpha属性 Gdx.gl.glBlendFunc ...

  6. R绘图 第五篇:绘制散点图(ggplot2)

    ggplot2包中绘制点图的函数有两个:geom_point和 geom_dotplot,当使用geom_dotplot绘图时,point的形状是dot,不能改变点的形状,因此,geom_dotplo ...

  7. OLEDB数据源和目标组件

    在SSIS工程的开发过程中,OLEDB 数据源和目标组件是最常用的数据流组件.从功能上讲,OLEDB 数据源组件用于从OLEDB 提供者(Provider)中获取数据,传递给下游组件,OLEDB提供者 ...

  8. tree的使用,显示行号,find命令应用

    第1章 linux启动过程 1.开机自检bios 2.mbr引导 3.GRUB 菜单:选择不同的内核 4.加载内核 5.运行init进程 6.读取/etc/inittab运行级别配置文件 7.执行 / ...

  9. grunt-inline:一个资源内嵌插件

    一.插件简介 将引用的外部资源,如js.css.img等,内嵌到引用它们的文件里去. 二.使用场景 在项目中,出于某些原因,有的时候我们需要将一些资源,比如js脚本内嵌到页面中去.比如我们的html页 ...

  10. 微信小程序获取客户端系统信息

    微信小程序中有个API: wx.getSystemInfo() 可以获取系统的信息 wx.getSystemInfoSync()===>同步获取系统信息 wx.getSyatemInfo({ s ...