LOJ#6118 鬼牌
:是我假了...这题没有爆精...大家要记得这道题是相对误差...感谢@foreverlasting的指正。
题是好题,可是标算爆精是怎么回事...要写的和标算一毛一样才能过。
各位要写的话过了前5个点就当过了吧...
题意
你有张牌,每张牌上有一个的点数,你每次随机选出两张不同的牌和,并将的点数变为的点数。求将所有牌的点数变成一样的期望步数。用输出。,。
题解
那首先有个挺显然的想法是枚举最终变成了哪种牌,那么所有牌就变成了是这种牌与不是这种牌两类。我们这么计算这种情况的贡献:
假如若干步以后,是这种牌的数量变为,则这种情况的贡献为。
否则,若干步以后是这种牌的数量变为,则这种情况的贡献为。
那么只要把每种牌的这个答案加起来就好了。
现在我们要解决的问题是:有两种牌,第一种有张,第二种有张,问最终全变为第一种牌的贡献。
很显然当固定的时候,答案只和有关。于是我们将其记为。
在计算之前,我们先来计算辅助数组。其中表示有两种牌,第一种有张,第二种有张,问最终全变为第一种牌的概率。
怎么求呢?首先边界条件有,,再来考虑一般的情况。
我们来考虑一下第一次对牌数有影响的操作。假如是第一种牌,是第二种牌,那么第一种牌数;假如是第二种牌,是第一种牌,那么第一种牌数。显然这两种情况的方案数是一样的,于是可以得出会等概率变成或,于是就可以得到一个简单的式子:
于是移项得到:
可以发现每一项都依赖前两项,于是我们设,则可计算出,,,那么显然我们可以猜想,可以通过归纳法证明其是成立的。
于是得到,解得。
因此当第一种牌数为时,最终全变成第一种牌的概率为。
现在来考虑求,边界条件有,,一般情况显然还是可以归纳成和的情况。不过这次还要额外考虑一些事情:
以变成为例,首先我们枚举在几步以后变成。设没有影响的操作发生概率为,使变为的操作发生概率为。则可得到期望额外花费的步数为:
整理得其为。
还要注意的是由于规约到的情况后成功的概率是,而失败的贡献是,因此期望步数只有是有效的,贡献为。
对于的情况,和是一样的,因此贡献为。两者相加为。
可以计算得,。于是原式可化简为:
因此可以得到:
移项可得:
依然设,则,,,依然可以通过观察和归纳法证明:
那么对于:
可解得。
于是继续对的式子进行化简:
我们设为调和数,即,则第二项等于:
继续推导第三项:
将三项合并,最终得到:
那么问题来了,那么大,怎么求呢?标算的做法是将小的调和数预处理,大的用来近似,其中为欧拉常数。但是不知道为啥标算的取的是...不过实测下来就算预处理前的调和数以及用较精确的欧拉常数后面的误差也在左右...再乘以一个大常数算答案精度堪忧。
这里再提供一个精度靠谱复杂度也有保证的做法。注意到答案中计算贡献的调和数其实类似于倒数的后缀和,因此较小的时候显然可以预处理。可以设一个阈值,预处理前个后缀和,剩下的数不会超过个,可以用分段打表暴力处理。由于查询量不是很大,打表的间隔可以取大一点减少代码长度。
还有由于答案有点大最好开或者自己写精度更高的类型...~~不过反正标算都爆精了这些好像也是后话了。~~这么好的题为什么不取模呢,用第二种做法就很靠谱了。