P4223 期望逆序对
首先,期望数乘上 \(\dbinom n2^k\) 后得到的就是所有方案的逆序对数之和。
任取两个位置 \(A, B(A < B)\),不难看出其他任意位置对 \(A, B\) 而言都是等价的,把这些位置统称为 \(C\) 位置。
然后 \((A, B)\) 最终的样子只有以下七种形式:\((A, B), (A, C), (B, A), (B, C), (C, A), (C, B), (C, C)\),把这七种形式从 \(1\) 到 \(7\) 编号。
设 \(f_j(i)\) 表示交换 \(i\) 次后形如第 \(j\) 种形式的方案数:
\(k \le 10^9\),考虑矩阵优化,写出转移矩阵:
\[T = \begin{bmatrix}
\binom{n - 2}2 & 1 & 1 & 0 & 0 & 1 & 0 \\
n - 2 & \binom{n - 2}2 + (n - 3) & 0 & 1 & 1 & 0 & 1 \\
1 & 0 & \binom{n - 2}2 & 1 & 1 & 0 & 0 \\
0 & 1 & n - 2 & \binom{n - 2}2 + (n - 3) & 0 & 1 & 1 \\
0 & 1 & n - 2 & 0 & \binom{n - 2}2 + (n - 3) & 1 & 1 \\
n - 2 & 0 & 0 & 1 & 1 & \binom{n - 2}2 + (n - 3) & 1 \\
0 & n - 3 & 0 & n - 3 & n - 3 & n - 3 & \binom{n - 2}2 + 2(n - 4) + 1
\end{bmatrix}
\]
则有:
\[T^k \times \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \\0 \end{bmatrix} = \begin{bmatrix} f_1(i) \\ f_2(i) \\ f_3(i) \\ f_4(i) \\ f_5(i) \\ f_6(i) \\ f_7(i) \end{bmatrix}
\]
其中 \(f_1(0) = 1, f_2(0) = f_3(0) = \dots = f_7(0) = 0\)。
然后我们开始枚举数对 \((i, j)(i < j)\),若 \(a_i < a_j\):
- \((A, B)\),必然没有贡献。
- \((A, C)\),\(C\) 在 \(A\) 前就有贡献,贡献为 \(\dfrac{i - 1}{n - 2} \times f_2(k)\)。
- \((B, A)\),必然有贡献,贡献为 \(f_3(k)\)。
- \((B, C)\),\(C\) 在 \(B\) 前且不是 \(A\) 就有贡献,贡献为 \(\dfrac{j - 2}{n - 2} \times f_4(k)\)。
- \((C, A)\),\(C\) 在 \(A\) 后且不是 \(B\) 就有贡献,贡献为 \(\dfrac{n - i - 1}{n - 2} \times f_5(k)\)。
- \((C, B)\),\(C\) 在 \(B\) 后就有贡献,贡献为 \(\dfrac{n - j}{n - 2} \times f_6(k)\)。
- \((C, C)\),相对位置交换成 \((j, i)\) 且不在 \(A\) 或 \(B\) 就有贡献,贡献为 \(\dfrac 12 f_7(k)\)。
同理可推知 \(a_i > a_j\) 的具体情况。
套 BIT 优化以下,时间复杂度 \(\mathcal O(7^3\log k + n \log n)\)。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
constexpr int N = 5e5 + 10, MOD = 1e9 + 7, INV2 = 5e8 + 4;
int n, k, a[N];
struct Matrix {
ll a[7][7];
Matrix operator*(const Matrix &rhs) const {
Matrix res; memset(res.a, 0, sizeof(res.a));
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++) {
for (int k = 0; k < 7; k++) {
res.a[i][j] = (res.a[i][j] + a[i][k] * rhs.a[k][j]) % MOD;
}
}
}
return res;
}
} trans, fk;
struct BIT {
ll c[N];
void fix(int x, int val) {for (int i = x; i <= n; i += i & (-i)) c[i] += val;}
ll query(int x) {ll res = 0; for (int i = x; i; i -= i & (-i)) res += c[i]; return res % MOD;}
} b1, b2, b3;
inline ll inv(ll base, int e = MOD - 2) {
ll res = 1;
while (e) {
if (e & 1) res = res * base % MOD;
base = base * base % MOD;
e >>= 1;
}
return res;
}
signed main() {
ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> k; ll c2 = (1ll * (n - 2) * (n - 3) / 2) % MOD;
for (int i = 1; i <= n; i++) cin >> a[i];
trans = Matrix{{
{c2, 1, 1, 0, 0, 1, 0},
{n - 2, c2 + n - 3, 0, 1, 1, 0, 1},
{1, 0, c2, 1, 1, 0, 0},
{0, 1, n - 2, c2 + n - 3, 0, 1, 1},
{0, 1, n - 2, 0, c2 + n - 3, 1, 1},
{n - 2, 0, 0, 1, 1, c2 + n - 3, 1},
{0, n - 3, 0, n - 3, n - 3, n - 3, c2 + 2 * (n - 4) + 1}
}}, fk.a[0][0] = 1;
while (k) {
if (k & 1) fk = trans * fk;
trans = trans * trans;
k >>= 1;
}
ll ans = 0, invn = inv(n - 2), f[8];
for (int i = 1; i <= 7; i++) f[i] = fk.a[i - 1][0];
for (int i = 1; i <= n; i++) {
ll s1l = b1.query(a[i]), sil = b2.query(a[i]), snl = b3.query(a[i]), s1r = (b1.query(n) - s1l + MOD) % MOD, sir = (b2.query(n) - sil + MOD) % MOD, snr = (b3.query(n) - snl) + MOD % MOD;
ans = (ans + s1r * f[1]) % MOD;
ans = (ans + (sil + snr) * invn % MOD * f[2] % MOD) % MOD;
ans = (ans + s1l * f[3]) % MOD;
ans = (ans + (s1l * (i - 2) + s1r * (n - i)) % MOD * invn % MOD * f[4]) % MOD;
ans = (ans + (snl + sir) * invn % MOD * f[5]) % MOD;
ans = (ans + (s1l * (n - i) + s1r * (i - 2)) % MOD * invn % MOD * f[6]) % MOD;
b1.fix(a[i], 1), b2.fix(a[i], i - 1), b3.fix(a[i], n - i - 1);
}
ans = (ans + 1ll * n * (n - 1) / 2 % MOD * f[7] % MOD * INV2) % MOD;
cout << ans;
return 0;
}