[YNOI2019]游戏

题目

  (原题题意不清)有\(n\)个人玩,开始时从\(1\)号到\(n\)依次排队。每轮游戏有\(4\)人参加,一轮游戏中每位玩家胜率相等,胜者将称为擂主继续游戏,剩下三位将按照入场顺序排在队尾,接下来按队列继续游戏。如果擂主在本轮输了,将排在剩下两名输了的选手的前面。获得最终胜利的条件为连胜\(m\)。最后询问第\(k\)个人获得最终胜利的概率。\(4\leqslant n\leqslant10\)\(k\leqslant n\)\(m\leqslant 10\)

题解

  难在状态设计。状态也许依赖于顺序,但仔细想一想可以发现我们只关心第\(k\)个人的位置以及擂主的连胜数(不管他是谁)。于是可以得到状态\(f_{i,j}\)表示第\(k\)个人在从前往后的第\(j\)个位置,当前擂主(站在第一位的)连胜\(i\)场时第\(k\)个人能获得最终胜利的概率。显然\(f_{m,1}=1\)\(f_{m,i}=0(i\ne1)\)。接着我们分类讨论:

\(k\)个人是擂主,即\(j=1\)

  那么守擂成功的概率为\(25\%\),失败的概率为\(75\%\),分别对应到状态\(f_{i+1,1}\)\(f_{1,n-2}\)(在另外两人之前),即

\[f_{i+1,1}\leftarrow f_{i,1}\times25\% \]

\[f_{1,n-2}\leftarrow\sum_{i=0}^{m-1}f_{i,1}\times75\% \]

其他人是擂主,即\(j\ne1\)

  稍微复杂了些。分为\(k\)在前四个人中以及\(k\)不在前四个人中。然后还要细分。

  当\(j=2,3,4\)时,第\(k\)个人均有\(25\%\)的概率获胜,此时会转移到\(f_{1,1}\),即

\[f_{1,1}\leftarrow 25\%\times\sum_{i=0}^{m-1}f_{i,2}+f_{i,3}+f_{i,4} \]

  对于剩下的\(75\%\)\(j\)一定会跑到队尾,具体在哪里仍然要细分。

  当\(j=2\)时,仍然要考虑擂主会不会获胜。仍然有\(25\%\)的概率擂主会获胜,此时第\(k\)个人会到第\(n-2\)个位置,即到达\(f_{i+1,n-2}\);如果擂主失败,那么对于\(k\)获胜的情况上面讨论过,剩下\(50\%\)另外两人获胜,擂主连胜次数变成\(1\),但注意此时\(k\)会跑到\(n-1\)的位置因为擂主要排在他前面,即转移成\(f_{1,n-1}\),即

\[f_{i+1,n-2}\leftarrow25\%\times f_{i,2} \]

\[f_{1,n-1}\leftarrow50\%\times\sum_{i=0}^{m-1}f_{i,2} \]

  当\(j=3\)时,同上,如果擂主连胜,有\(25\%\)的概率转移到\(f_{i+1,n-1}\);如果其它两人获胜,要细分是\(k\)前面的人还是后面的人(因为这会影响到队列顺序)。如果前面的人赢了,\(k\)号会排到\(n-1\)位,即\(25\%\)的概率转移到\(f_{1,n-1}\);如果后面的人赢了,\(k\)会排到\(n\)位,即\(25\%\)的概率转移到\(f_{1,n}\),即

\[f_{i+1,n-1}\leftarrow25\%\times f_{i,3} \]

\[f_{1,n-1}\leftarrow25\%\times\sum_{i=0}^{m-1}f_{i,3} \]

\[f_{1,n}\leftarrow25\%\times\sum_{i=0}^{m-1}f_{i,3} \]

  当\(j=4\)时,继续分析,得到下面

\[f_{i+1,n}\leftarrow25\%\times f_{i,4} \]

\[f_{1,n}\leftarrow50\%\times\sum_{i=0}^{m-1}f_{i,4} \]

  其余情况下,第\(k\)个人只会前进\(3\)位,分为两种情况

\[f_{i+1, j-3}\leftarrow25\%\times f_{i,j} \]

\[f_{1,j-3}\leftarrow75\%\times f_{i,j} \]

  最后根据以上的关系式列方程,gauss消元即可,最终答案为\(f_{0,k}\)。状态集\(\mathcal O(nm)\),复杂度\(\mathcal O(n^3m^3)\)

  听说还有\(\mathcal O(n^2m+n^3)\)的复杂度?这里\(\text{%%%C}\color{red}{\text{razysky}}\)。发现所有转移都是要么往连胜次数\(i+1\)要么往\(1\),构成环的关键是从\(f_{i,j}\)跳到了\(f_{1,j}\)。这里把所有的\(f_{1,x}\)看成未知数,然后一级一级往上列出\(f_{i,j}\)\(f_{1,x}\)的关系,回到\(f_{1,x}\)的恰好能列出来方程,最后能得到\(\mathcal O(nm)\)个方程,右边是\(f_{1,x}\),左边是\(\sum f_{1,i}\)。把右边相同的合并起来,最后合并成\(n\)个方程,再进行gauss消元,就能做到这个复杂度了。

代码

  直接gauss消元的做法。

#include <bits/stdc++.h>

#define rep(i, a, b) for (int i = a, i##end = b; i <= i##end; ++i)
#define per(i, a, b) for (int i = a, i##end = b; i >= i##end; --i)
#define rep0(i, a) for (int i = 0, i##end = a; i < i##end; ++i)
#define per0(i, a) for (int i = a-1; ~i; --i)

const int maxn = 15;

int n, m, k;
double a[maxn*maxn][maxn*maxn];

void Gauss(int n) {
    rep(i, 1, n) {
        int r = i;
        rep(j, i+1, n) if (fabs(a[j][i]) > fabs(a[r][i])) r = j;
        if (r != i) rep(j, 1, n+1) std::swap(a[r][j], a[i][j]);
        rep(j, 1, n) if (j != i) {
            double t = a[j][i] / a[i][i];
            rep(k, 1, n+1) a[j][k] -= t * a[i][k];
        }
    }
    rep(i, 1, n) a[i][n+1] /= a[i][i];
}

#define id(i, j) ((i)*n+(j))

int main() {
    for (int T = read(); T; T--) {
        n = read(), m = read(), k = read();
        memset(a, 0, sizeof a);
        rep(i, 0, m)
            rep(j, 1, n)
                a[id(i, j)][id(i, j)] = 1;
        a[id(m, 1)][n*(m+1)+1] = 1;
        rep0(i, m) {
            a[id(i, 1)][id(i+1, 1)] -= 0.25;
            a[id(i, 1)][id(1, n-2)] -= 0.75;
            a[id(i, 2)][id(1, 1)] -= 0.25;
            a[id(i, 3)][id(1, 1)] -= 0.25;
            a[id(i, 4)][id(1, 1)] -= 0.25;
            a[id(i, 2)][id(i+1, n-2)] -= 0.25;
            a[id(i, 2)][id(1, n-1)] -= 0.5;
            a[id(i, 3)][id(i+1, n-1)] -= 0.25;
            a[id(i, 3)][id(1, n-1)] -= 0.25;
            a[id(i, 3)][id(1, n)] -= 0.25;
            a[id(i, 4)][id(i+1, n)] -= 0.25;
            a[id(i, 4)][id(1, n)] -= 0.5;
            rep(j, 5, n)
                a[id(i, j)][id(i+1, j-3)] -= 0.25,
                a[id(i, j)][id(1, j-3)] -= 0.75;
        }
        Gauss(n*(m+1));
        printf("%.6lf\n", a[id(0, k)][n*(m+1)+1]);
    }
    return 0;
}
posted @ 2020-03-22 10:58  AC-Evil  阅读(223)  评论(0编辑  收藏  举报