[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);
}

posted @ 2023-03-15 21:52  RiverSheep  阅读(22)  评论(0编辑  收藏  举报