小红的点赞题解

显然,这道题具体的数是多少并不重要

我们只关心奇数与偶数的个数

为奇数个数为时的还原为偶数的期望 我们有

对于

此处不依赖数学直觉,将其转换为 使得而是选择高斯消元

对于每一个表达式 有 可列出行列式

1 0 0 ... ... ... ... 0
1 ... ... ... ... 1
0 1 ... ... ... 1
... ... ... ... ... ... ... 1
... ... ... ... 1 1
... ... ... ... ... -1 1 1

显然,只需要解出该行列式对应的方程组就可求出对应的

但高斯消元的时间复杂度为不可能通过的数据

注意到该行列式十分特殊,每行最多只有三个值

此处使用TDMA(Thomas Algorithm)托马斯算法进行计算

本质其实是高斯消元剪枝,先只使用上一行的进行消元,变成上三角矩阵

再只使用下一行数据获取答案,具体做法请自行搜索

def thomas_algorithm(n, a, b, c, d):
    """
    求解方程组: 
    b[0] * x[0] + c[0] * x[1] = d[0]
    a[i] * x[i-1] + b[i] * x[i] + c[i] * x[i+1] = d[i], for i=1 to n-2
    a[n-1] * x[n-2] + b[n-1] * x[n-1] = d[n-1]
    """
    # 前向消元
    for i in range(1, n):
        w = a[i] / b[i-1]
        b[i] = b[i] - w * c[i-1]
        d[i] = d[i] - w * d[i-1]
    
    # 回代
    x = [0] * n
    x[n-1] = d[n-1] / b[n-1]
    for i in range(n-2, -1, -1):
        x[i] = (d[i] - c[i] * x[i+1]) / b[i]
    
    return x

如此便解决该题,附通过代码

#include <bits/stdc++.h>
using namespace std;
constexpr int mod = 1e9 + 7;
int pow(int a, int b, const int &m)
{
    long long res = 1, po = a;
    for (; b; b >>= 1)
    {
        if (b & 1)
            res = res * po % m;
        po = po * po % m;
    }
    return res;
}

// Returns the modular inverse of a prime modulo p.
int64_t inverse(int a, int p = mod)
{
    return pow(a, p - 2, p);
}
int main()
{
    int n;
    cin >> n;
    int64_t sum = 0;
    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        sum += x;
        cnt += x & 1;
    }
    vector<int64_t> c(n + 1, 1);
    c[0] = 0;
    vector<array<int64_t, 3>> a(n + 1);
    a[0] = {0, 1, 0};
    int64_t inv_n = inverse(n);
    for (int i = 1; i < n; i++)
    {
        a[i][0] = (mod - i) * inv_n % mod;
        a[i][1] = 1;
        a[i][2] = (mod - (n - i)) * inv_n % mod;
    }
    a[n][0] = mod - 1;
    a[n][1] = 1;
    a[n][2] = 0;
    for (int i = 1; i <= n; i++)
    {
        int t = a[i][0] * inverse(a[i - 1][1]) % mod;
        for (int j = 1; j < 3; j++)
        {
            a[i][j - 1] -= t * a[i - 1][j] % mod;
            a[i][j - 1] = (a[i][j - 1] + mod) % mod;
        }
        c[i] -= (c[i - 1] * t) % mod;
        c[i] = (c[i] + mod) % mod;
    }
    for (int i = n - 1; i >= 0; i--)
    {
        int t = a[i][2] * inverse(a[i + 1][1]) % mod;
        for (int j = 1; j <= 2; j++)
        {
            a[i][j] -= t * a[i + 1][j - 1] % mod;
            a[i][j] = (a[i][j] + mod) % mod;
        }
        c[i] -= (c[i + 1] * t) % mod;
        c[i] = (c[i] + mod) % mod;
    }
    cout << (sum + c[cnt] * inverse(a[cnt][1]) % mod) % mod;
    return 0;
}