Link:
Luogu https://www.luogu.com.cn/problem/AT4513
Description
相当于,是要
给定 Q 次操作,每个操作指定两下标
等概率地,可能执行或者不执行讲这两个下标对应的数字对换的操作
求 Q 次操作之后,逆序数的期望。
Solution
观察复杂度
发现可以存下 (O(n^2))
所以直接存下现在进行了 (q) 次操作之后,每个数对是逆序的概率
……为什么可以这么做?
当然可以这么做啊。
转移:
[p'(i,a)=p'(i,b)=frac{p(i,a)+p(i,b)}{2}
]
注意一下特殊情况就好
出错用 // * 标记
(没想到这里 system("pause") 没删掉也能过.jpg
Code
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cctype>
#include<cmath>
using namespace std;
const int MAXN = 3005;
int n, q, a[MAXN];
const long long MOD = 1e9 + 7, INV2 = (MOD + 1) >> 1;
long long p[MAXN][MAXN], Ans = 0, Multi = 1;
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
for (int j = 1; j < i; ++j)
{
p[j][i] = (a[j] > a[i]);
p[i][j] = (a[i] > a[j]);
}
}
for (int x, y, c = 1; c <= q; ++c)
{
scanf("%d%d", &x, &y);
for (int i = 1; i <= n; ++i)
{
if (i == x || i == y) continue;
p[x][i] = p[y][i] = (p[x][i] + p[y][i]) * INV2 % MOD;
p[i][x] = p[i][y] = (p[i][x] + p[i][y]) * INV2 % MOD;
}
p[x][y] = p[y][x] = (p[x][y] + p[y][x]) * INV2 % MOD; // *
Multi <<= 1;
Multi %= MOD;
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j < i; ++j)
{
Ans += p[j][i]; // *
}
}
Ans %= MOD;
Ans *= Multi;
Ans %= MOD;
printf("%lld", Ans);
// system("pause"); *
return 0;
}