[ARC154E] Reverse and Inversion
[ARC154E] Reverse and Inversion
先化简\(f(P)\),考虑每一个 \(i\) 的贡献,它等于
\[\sum_ii*(\sum_{j<i}[P_j > P_i] - \sum_{j > i}[P_j < P_i])
\]
因为\(\sum_{j<i}[P_j > P_i] = i - 1 - (P_i - 1 - \sum_{j > i}[P_j < P_i]))\)
所以原式为
\[\sum_ii^2 - \sum_iiP_i
\]
现在的关键就是求出\(\sum iP_i\),因为对于每一种方案的值都要求出,相当于求出其期望值。
考虑 \(i\) 期望被交换到哪个位置,假设 一次操作后 \(i\) 被交换到 \(j\),其概率为 \(\frac{2min(i, j, n - i + 1, n - j + 1)}{n(n+1)}\),观察发现 \(i\) 交换到 \(n - j + 1\) 的概率和其是一样的,所以如果 \(i\) 被操作过,其期望位置为 \(\frac{n +1}{2}\),否则为位置为 \(i\)。
易得位置 \(i\) 没被操作的概率为 \(p_i = (1 - \frac{2i(n - i +1)}{n(n+1)})^m\),那么 \(\sum iP_i\) 的期望值为 \(\sum P_i(p_i * i + (1 - p_i)*\frac{n + 1}{2})\)。
Code
#include<cstdio>
#include<iostream>
#define IN inline
#define LL long long
using namespace std;
const int N = 2e5 + 5, P = 998244353;
LL a[N], p[N], n, m;
IN int read() {
int t = 0,res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
return t ? -res : res;
}
LL fpow(LL x, LL y) {
LL res = 1; y = y % P;
for (; x; x >>= 1, y = y * y % P)
if (x & 1) res = res * y % P;
return res;
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++) a[i] = read();
LL inv = fpow(P - 2, n * (n + 1) / 2), iv2 = fpow(P - 2, 2LL);
for (LL i = 1; i <= n; i++) p[i] = fpow(m, (P + 1 - (LL)i * (n - i + 1) % P * inv % P) % P);
LL ans = 0;
for (LL i = 1; i <= n; i++)
(ans += P + i * i % P - a[i] * (p[i] * i % P + (1 + P - p[i]) * (n + 1) % P * iv2 % P) % P) %= P;
printf("%lld\n", ans * fpow(m, n * (n + 1) / 2) % P);
}