原题解链接:https://ac.nowcoder.com/discuss/150009

一个简单的期望dpdp。用std::vector与std::map暴力存下状态,O(n)O(n) 转移。转移时枚举 选到了哪个数,根据后继状态更新当前状态。注意当前状态的后继有可能还是自己,那么只要移 一下项就可以计算了。

fst=p1fnxt1+p2fnxt2++pkfstf_{s t}=p_{1} f_{n x t_{1}}+p_{2} f_{n x t_{2}}+\ldots+p_{k} f_{s t}

转移的式子是这样的,其中有Pe的概率转移到自身,那么我们整理可得:

(1pk)fst=p1fnxt1+p2fnxt2++pk1fnxtk1\left(1-p_{k}\right) f_{s t}=p_{1} f_{n x t_{1}}+p_{2} f_{n x t_{2}}+\ldots+p_{k-1} f_{n x t_{k-1}}

处理一下边界就可以了。至于状态数,我们考虑每一次操作之间顺序是不重要的。即先选到aa再选到bb和先选到bb再选到aa最终的状态是相同的。那么状态数就是0(2n)0(2^n)的,可以通过此题。

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
long long MOD = 998244353;
long long inv[30];
int n;
int b[30];
vector<int> a;
long long res[1 << 20];

long long power(long long b, long long p)
{
    long long t = b, res = 1;
    while (p)
    {
        if (p & 1) res = res * t % MOD;
        t = t * t % MOD;
        p >>= 1;
    }
    return res;
}
int main()
{
    for (int i = 1; i < 30; i ++) inv[i] = power(i, MOD - 2);
    cin >> n;
    for (int i = 0, k; i < n; i ++)
    {
        cin >> k;
        a.push_back(k);
        b[k] = i;
    }
    memset(res, -1, sizeof res);
    bool k = true;
    for (int i = 0; i < n && k; i ++)
        if (a[i] != i + 1) k = false;
    if (k)
    {
        cout << 0 << endl;
        return 0;
    }
    for (int i = 0; i < (1 << n); i ++)
    {
        int lst = -1;
        res[i] = 0;
        for (int j = 1; j <= n; j ++)
        {
            if (i & (1 << (j - 1))) lst = -1;
            else
            {
                if (b[j] < lst)
                {
                    res[i]  = - 1;
                    break;
                }
                lst = b[j];
            }
        }
    }
    for (int i = (1 << n) - 1; i >= 0; i --)
    if (res[i])
    {
        int t = 0;
        res[i] = n;
        for (int j = 0; j < n; j ++)
        {
            if (i & (1 << j)) t ++;
            else res[i] = (res[i] + res[i | (1 << j)]) % MOD;
        }
        res[i] = res[i] * inv[n - t] % MOD;
    }
    cout << res[0] << endl;
    return 0;
}