• jzoj4212. 【五校联考1day2】我想大声告诉你


    Description

    因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一些人,小R 自然也参加了。
    这个游戏有n 个人参加,每一轮随机选出一个还没有出局的人x,接着x 会出局。x 在出局之后剩下的人会受到一次攻击,每一个人在遭到攻击之后会有p 的概率出局。(注意遭到攻击出局的人是不能攻击剩下的人的)
    在所有人都出局之后,遭受攻击次数等于特定值的人能够成为胜者。所以现在小R 想要知道对于每一个0 <= k < n,自己恰好在遭受k 次攻击之后出局的概率是多少。(这里的出局指的不是被攻击出局)
    注意在这题中,所有数值的运算在模258280327 的意义下进行。

    Input

    第一行输入一个正整数T 表示数据组数。
    对于每一组数据输入仅一行三个数n, x, y,表示在这组数据中有n 个人参赛,p = x/y。保证y 和258280327 互质。

    Output

    对于每组数据,输出一行n 个整数,表示对于k = 0到n - 1 的概率在模258280327 意义下的值。

    Sample Input

    2
    3 40 100
    9 32 1049

    Sample Output

    172186885 92980918 16529941
    229582513 163885050 39458156 102374877 116777758 216371874 55544199 95860736 8136787

    Data Constraint

    对于60% 的数据,n <=100
    对于100% 的数据,n <= 2* 10^3,1 <= T <= 5,0<= x < y <= 10^9

    题解

    这题真的很有趣,比赛时玩一玩很好。
    我打死也不告诉你我玩完后没有预处理导致时超并且比赛时间不够导致爆0

    60%
    这档部分分很不错,只是与100分相去甚远。
    我们为了好表示,出局代表小R被选出去,淘汰表示小R被攻击而淘汰。
    看到题目我们考虑f[i,j,0…1]表示这个小R被攻击了i次后,不出局或出局,剩下j个人的概率。
    转移就稍微要注意一下了。
    首先我们考虑从i-1转移到i。
    那么我们枚举i-1状态时剩下的人k以及当前i状态时剩下的人j。
    注意i-1状态是已经有一个人出局但未攻击。
    而这个i状态是上一个人(非小R)已经攻击完且小R未淘汰。
    所以转移方程大致为:
    f[i,j,0]+=f[i1,k,0]pkj(1p)jc(j1,k1);f[i,j,0]+=f[i-1,k,0]*p^{k-j}*(1-p)^j*c(j-1,k-1);
    什么意思呢?
    就是上一个状态攻击有k-j个人淘汰,j个人存活。
    由于每个人都不相同,所以我们还要考虑组合数。
    就是在剩下除了小R的人中任意选j-1个人存活。
    这个转移是O(n3)O(n^3)
    然后接下来我们还要维护这个f[i,j,1].
    f[i,j,1]:=f[i,j+1,0]/(j+1);f[i,j,1]:=f[i,j+1,0]/(j+1);
    然后再把小R出局后的情况给更新f[i,j,0]即可。
    f[i,j,0]:=f[i,j+1,0]j/(j+1);f[i,j,0]:=f[i,j+1,0]*j/(j+1);
    这样就可以做到O(n3)O(n^3),注意预处理。

    当然,如果想把这个方法利用前缀和之类的优化来优化似乎是可以的。
    但是我不会。
    所以我们考虑换一种思路来想。

    100%
    我们考虑把每个人出局或淘汰的顺序来进行DP
    我们发现,由于每次出局的人是随意的,每次淘汰的人也是不定的。
    所以我们就不必关心不同的人的不同淘汰或出局顺序
    设f[i,j]表示当前1 ~ i的顺序的人都淘汰或出局(i+1 ~ n的顺序人不理会),i+1 ~ n的人受到j次攻击的概率。
    所以我们就考虑怎么从前面的状态转移到i这个位置。
    分类讨论

    1、当i这个人是出局的,那么这个i必然是在经过j-1次攻击后存活下来的,并且对后面进行了攻击。
    f[i,j]+=f[i1,j1](1p)j1f[i,j]+=f[i-1,j-1]*(1-p){j-1}
    2、当i这个人是淘汰的,那么这个i必然是在前面j次攻击时其中一个挂掉的,并且不会对后面攻击。
    f[i,j]+=f[i1,j](1(1p)j)f[i,j]+=f[i-1,j]*(1-(1-p)^{j})
    然后就转移完了。
    很巧妙,对吗?
    初始化f[0,0]:=1;f[0,0]:=1;

    然后统计答案。
    我们考虑枚举小R是第几个挂掉的。
    那么答案即为:i=0n1j=0n1f[i,j](1p)j/nsum_{i=0}^{n-1}sum_{j=0}^{n-1}f[i,j]*(1-p)^j/n
    表示小R是在i+1这个位置出局的概率,由于之前小R都没有出局,那么小R必然是正常出局。
    后面这个/n表示小R在i+1这个位置出局的概率。
    时间是O(n2)O(n^2)的。

    代码

    60%

    {$inline on}
    var
            i,j,k,l,n,m,t:longint;
            x,y,p,q,answer:int64;
            mo:int64=258280327;
            f,g:array[0..2001,0..2001,0..1] of int64;
            op,oq:array[0..2000] of int64;
            jc:array[0..2000] of int64;
            c:array[-1..2000,-1..2000] of int64;
    function qsm(a,b:int64):int64;inline;
    var
            t,y:int64;
    begin
            t:=1;
            y:=a;
            while b<>0 do
            begin
                    if(b and 1)=1 then
                            t:=(t*y) mod mo;
                    y:=(y*y) mod mo;
                    b:=b shr 1;
            end;
            exit(t);
    end;
    function cc(m,n:longint):int64;inline;
    begin
            if m=n then exit(1);
            if m=0 then exit(1);
            if n=0 then exit(1);
            exit(jc[n]*qsm(jc[m]*jc[n-m] mod mo,mo-2) mod mo);
    end;
    begin
            jc[0]:=1;
            jc[1]:=1;
            for i:=2 to 2000 do
            begin
                    jc[i]:=jc[i-1]*i mod mo;
            end;
            c[0,0]:=1;
            for i:=0 to 2000 do
            begin
                    c[0,i]:=1;
                    for j:=1 to 2000 do
                    begin
                            c[j,i]:=(c[j,i-1]+c[j-1,i-1]) mod mo;
                    end;
            end;
            for i:=0 to 2000 do c[0,i]:=1;
            readln(t);
            while t>0 do
            begin
                    dec(t);
                    readln(n,x,y);
                    fillchar(f,sizeof(f),0);
                    p:=x*qsm(y,mo-2) mod mo;
                    q:=(y-x)*qsm(y,mo-2) mod mo;
                    op[0]:=1;
                    oq[0]:=1;
                    for i:=1 to 2000 do
                    begin
                            op[i]:=op[i-1]*p mod mo;
                            oq[i]:=oq[i-1]*q mod mo;
                    end;
                    f[0,n-1,0]:=(n-1)*qsm(n,mo-2) mod mo;
                    f[0,n-1,1]:=qsm(n,mo-2) mod mo;
                    for i:=1 to n-1 do
                    begin
                            for j:=1 to n do
                            begin
                                    for k:=j to n do
                                    begin
                                            //l:=cc(j-1,k-1);
                                            f[i,j,0]:=(f[i,j,0]+f[i-1,k,0]*op[k-j] mod mo*oq[j] mod mo*c[j-1,k-1]) mod mo;
                                    end;
                            end;
                            for j:=0 to n-1 do
                            begin
                                    f[i,j,1]:=f[i,j+1,0]*qsm(j+1,mo-2) mod mo;
                            end;
                            for j:=1 to n-1 do
                            begin
                                    f[i,j,0]:=f[i,j+1,0]*j mod mo*qsm(j+1,mo-2) mod mo;
                            end;
                    end;
                    for i:=0 to n-1 do
                    begin
                            answer:=0;
                            for j:=0 to n do
                            begin
                                    answer:=(answer+f[i,j,1]) mod mo;
                            end;
                            write(answer,' ');
                    end;
                    writeln;
            end;
    end.
    

    100%

    {$inline on}
    var
            i,j,k,l,n,m,t:longint;
            x,y,p,q,answer,ny:int64;
            mo:int64=258280327;
            f,g:array[0..2001,-1..2001] of int64;
            op,oq,ok:array[0..2000] of int64;
            jc:array[0..2000] of int64;
            c:array[-1..2000,-1..2000] of int64;
    function qsm(a,b:int64):int64;inline;
    var
            t,y:int64;
    begin
            t:=1;
            y:=a;
            while b<>0 do
            begin
                    if(b and 1)=1 then
                            t:=(t*y) mod mo;
                    y:=(y*y) mod mo;
                    b:=b shr 1;
            end;
            exit(t);
    end;
    function cc(m,n:longint):int64;inline;
    begin
            if m=n then exit(1);
            if m=0 then exit(1);
            if n=0 then exit(1);
            exit(jc[n]*qsm(jc[m]*jc[n-m] mod mo,mo-2) mod mo);
    end;
    begin
            jc[0]:=1;
            jc[1]:=1;
            for i:=2 to 2000 do
            begin
                    jc[i]:=jc[i-1]*i mod mo;
            end;
            c[0,0]:=1;
            for i:=0 to 2000 do
            begin
                    c[0,i]:=1;
                    for j:=1 to 2000 do
                    begin
                            c[j,i]:=(c[j,i-1]+c[j-1,i-1]) mod mo;
                    end;
            end;
            for i:=0 to 2000 do c[0,i]:=1;
            readln(t);
            while t>0 do
            begin
                    dec(t);
                    readln(n,x,y);
                    fillchar(f,sizeof(f),0);
                    p:=x*qsm(y,mo-2) mod mo;
                    q:=(y-x)*qsm(y,mo-2) mod mo;
                    op[0]:=1;
                    oq[0]:=1;
                    ok[0]:=1;
                    for i:=1 to 2000 do
                    begin
                            op[i]:=op[i-1]*p mod mo;
                            oq[i]:=oq[i-1]*q mod mo;
                            ok[i]:=ok[i-1]*q mod mo;;
                    end;
                    f[0,0]:=1;
                    for i:=1 to n do
                    begin
                            for j:=0 to i do
                            begin
                                    if j>0 then
                                    f[i,j]:=(f[i,j]+f[i-1,j-1]*ok[j-1] mod mo) mod mo;
                                    f[i,j]:=(f[i,j]+f[i-1,j]*(1-ok[j]+mo) mod mo) mod mo;
                            end;
                    end;
                    ny:=qsm(n,mo-2);
                    for i:=0 to n-1 do
                    begin
                            answer:=0;
                            for j:=0 to n-1 do
                            begin
                                    answer:=(answer+f[j,i]) mod mo;
                            end;
                            answer:=answer*ok[i] mod mo*ny mod mo;
                            write(answer,' ');
                    end;
                    writeln;
            end;
    end.
    
  • 相关阅读:
    Aras前端的一些知识
    Eclipse 实用快捷键大全
    Eclipse插件使用links目录的用法
    extjs portal 保存 事件
    NDRS SQL
    [VB]修改注册表让程序开机自动运行
    [C++]数组参数
    [C++]指针类型出参
    [C++]函数返回值
    [VBA]Excel输出utf8编码格式文件 使用WideCharToMultiByte
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148367.html
Copyright © 2020-2023  润新知