关于x/y,我们有公式x \equiv x^p (\mod p) \Rightarrow x^{-1} = x^{p-2}\mod p

so x/y = x \times y^{p-2}\mod{p}

对本题而言,显然在全1时必胜,不是全1时肯定选策略1

那么记录1的个数sum1,2的个数sum2,显然当前的胜率win(sum1, sum2)win(sum1-1,sum2)win(sum1+1,sum2-1)有关

那么取递归函数win表示当前赢的概率,参数分别为1的个数和2的个数,根据递归关系计算即可(返回值为分子分母)

(记得存已计算的值,不然重复递归会TLE)

#include <iostream>
#include <cstdio>
using namespace std;
#define LL long long

const LL mod = 1e9 + 7;

pair<LL,LL> f[1001][1001];

LL qpow(LL x, LL y)
{
    LL a = 1;
    x %= mod;
    while (y)
    {
        if (y&1) a = a * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return a;
}

pair<LL, LL> win(LL sum1, LL sum2)
{
    if (sum1 < 0)
        return {0l, 1l};
    if (sum2 == 0)
        return {1l, 1l};
    if (f[sum1][sum2].second != 0l)
        return f[sum1][sum2];
    //{sum1, (sum1 + sum2)%mod}, {sum2, (sum1 + sum2)%mod}
    pair<LL, LL> p1 = win(sum1-1, sum2), p2 = win(sum1+1, sum2-1), p3, p4;
    if (sum1 == 0)
        p3 = {0l, 1l};
    else
        p3.first = (p1.second-p1.first + mod) * sum1 % mod, p3.second = p1.second * (sum1 + sum2)%mod;
    p4.first = (p2.second-p2.first + mod) * sum2 % mod, p4.second = p2.second * (sum1 + sum2)%mod;

    f[sum1][sum2] = {(p3.first*p4.second%mod + p3.second*p4.first%mod)%mod, 
                p3.second*p4.second%mod};
    return f[sum1][sum2];
}

int main() 
{
    int n, a;
    LL sum1=0, sum2=0;
    cin >> n;
    for (int i=0; i <n; i ++)
    {
        cin >> a;
        if (a == 1)sum1++;
        else sum2++;
        f[i][0] = {1l, 1l};
        for (int j=1; j <n; j ++)
            f[i][j] = {0l, 0l};
    }
    f[0][0] = {0l, 1l};

    pair<LL,LL> ret = win(sum1, sum2);
    //cout << ret.first << " " << ret.second << endl;
    LL ans = qpow(ret.second, mod-2) * ret.first % mod;
    printf ("%lld\n", ans);
    return 0;
}