Live2D

Solution -「多校联训」光影交错

Description

  Link.

  一个游戏包含若干次卡牌抽取,每次以 pl 的概率得到 +1pd 的概率得到 1,否则得到 0,操作后以 p 的概率结束游戏,求每次抽取后,满足 +1 数量大于 1 数量的抽取轮数的期望值。不取模。

  0<p10pl,pd,pl+pd1

Solution

  我请愿为Tiw 太阳神教的教徒。(

  令 pe=1plpr,表示得到 0 的概率。我们直接从答案 A 入手:

A=l>d0,e0(l+d+el,d,e)pllpddpee(1p)l+d+e1,

即枚举一个抽取后(不一定结束)的状态。此后,把 (1p) 的指数分配到其余三个因子上,令

{pe=pe(1p)pl=pl(1p)pd=pd(1p),

带入 A,同时发现 e 的限制较少,所以单独枚举 e,有

A=11pl>d0,e0(l+d+el,d,e)peepddpll=11pld0(l+dd)pllpdde0(l+d+ee)pee.

  最后的级数形如 i0(i+ti)xi=1(1x)t,当 pe=1 时认为 100=1,即任意 pe 在这个 GF 的收敛域中,可以直接带入。所以

A=11pl>d0(l+dd)pllpdd1(1pe)l+d+1.

  按照先前的套路分配指数,再令

{pl=pl1pepd=pd1pe,

代入整理,得到

A=1(1p)(1pe)l>d0(l+dd)pllpdd.

  我们固定 l,挑出此时 d 的和式来研究,记

Sd(l)=0d<l(l+dd)pdd.

错位相减,左右乘 (1pd),对齐求和指标 d 以化简,最终得到

(1pd)Sd(l)=Sd(l1)+(2(l1)l1)pdl1(2l1l1)pdl.

al=(2(l1)l1)pdl1(2l1l1)pdl,自然得到

Sd(l)=i=0lai(1pd)li+1.

  代回 A,交换求和指标并分配 (1pd)li+1 的指数:

A=1(1p)(1pe)l0plli=1lai(1pd)li+1=1(1p)(1pe)i1ai(1pd)i+1li(pl1pd)l.

注意到最后的级数是等比数列求和,先考虑它的收敛性:

1pdpl=1(1p)pd+(1p)pl1(1p)pe=1(1p)pe(1p)pd(1p)pl1(1p)pe=p1(1p)pe>0.

收敛啦。不妨令 q=pl1pd,整理式子:

A=1(1p)(1pe)i1ai(1pe)i+1qi1q=1(1p)(1pe)(1q)i1qi{(2(i1)i1)[pd(1pd)]i1pd(2i1i1)[pd(1pd)]i1}=q(1p)(1pe)(1q)i1[(2(i1)i1)(pdpl)i1pd(2i1i1)(pdpl)i1].

  最后的最后,研究级数 i0(2ii)i0(2i1i)。考虑到 Catalan 数的 GF:

C(x)=i0(2ii)i+1xi=1(14x)122,

利用位移和求导消掉分母,得到 F(x)=i0(2ii)xi 的封闭形式:

[xC(x)]=[1(14x)122]=(14x)12=F(x).

接着用 F(x) 配凑出 G(x)=i0(2ii+1)xi,结果是

G(x)=1(14x)122x.

  将结果代入 A

A=q(1p)(1pe)(1q){(14pdpl)1212pl[(14pdpl)121]}

能直接 O(1) 计算啦。顺便检查一下 (14pdpl) 能否开根。注意到 pd+pl1,所以

pdpl(pl+pr)2414.

能开根,计算即可。注意特判 p=1pl=0 的情况(不然会爆 nan qwq)。

Code

/*~Rainybunny~*/

#include <cmath>
#include <cstdio>
#include <cassert>

#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 )

const int N = 1e7;
double pl, pd, pe, p, f[N + 5], g[N + 5];

inline void solve() {
    if ( p == 1 ) return void( printf( "%.12f\n", pl ) );
    if ( pl == 0 ) return void( printf( "%.12f\n", 0. ) );
    double c = pe * ( 1 - p ), // pe'
      a = ( 1 - p ) * pl / ( 1 - c ), // pl''
      b = ( 1 - p ) * pd / ( 1 - c ), // pd''
      q = a / ( 1 - b ), r = a * b, // pl''/(1-pd''); pl''pd''
      u = 1 / sqrt( 1 - 4 * r );
    printf( "%.12f\n", q / ( 1 - p ) / ( 1 - c ) / ( 1 - q )
      * ( !a || !b ? 1 : ( u - b / ( 2 * r ) * ( u - 1 ) ) ) );
}

int main() {
    freopen( "augury.in", "r", stdin );
    freopen( "augury.out", "w", stdout );

    int T;
    scanf( "%*d %d", &T );
    while ( T-- ) {
        scanf( "%lf %lf %lf", &pl, &pd, &p ), pe = 1 - pl - pd;
        solve();
    }
    return 0;
}

posted @   Rainybunny  阅读(60)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示