T3 AT4513 [AGC030D] Inversion Sum
题目大意: 给你一个长度为n的数列,然后给你q个交换或不交换操作,你可以选择操作或者不操作,问所有情况下逆序对的总和。
数据范围: n<=3e3 , q<=3e3
期望dp,
先转成期望,再乘上总的情况,设(dp[i][j]) 表示 (i > j) 的概率,然后具体的转移看代码。。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int N = 3010 , mod = 1e9+7 , inv2 = (mod + 1) / 2;
inline int read()
{
register int x = 0 , f = 0; register char c = getchar();
while(c < '0' || c > '9') f |= c == '-' , c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
return f ? -x : x;
}
int n , Q;
int a[N] , F[N][N] , G[N][N];
inline int add(int a , int b) { return a + b >= mod ? a - mod + b : a + b; }
inline int mul(int a , int b) { return (LL)a * b % mod; }
int main()
{
n = read(); Q = read();
for(int i = 1 ; i <= n ; ++i) a[i] = read();
for(int i = 1 ; i <= n ; ++i) for(int j = 1 ; j <= n ; ++j) F[i][j] = a[i] > a[j];
int p1 , p2 , res = 1;
while(Q--)
{
p1 = read(); p2 = read();
for(int i = 1 ; i <= n ; ++i) if(i != p1 && i != p2)
{
G[i][p1] = G[i][p2] = mul(inv2 , add(F[i][p1] , F[i][p2]));
G[p1][i] = G[p2][i] = mul(inv2 , add(F[p1][i] , F[p2][i]));
}
for(int i = 1 ; i <= n ; ++i) if(i != p1 && i != p2) F[i][p1] = G[i][p1] , F[i][p2] = G[i][p2] , F[p1][i] = G[p1][i] , F[p2][i] = G[p2][i];
F[p1][p2] = F[p2][p1] = mul(inv2 , add(F[p1][p2] , F[p2][p1]));
res = mul(res , 2);
}
int ans = 0;
for(int i = 1 ; i <= n ; ++i) for(int j = i + 1 ; j <= n ; ++j) ans = add(ans , F[i][j]);
cout << mul(res , ans) << '
';
return 0;
}