题目链接
题目解法
妙妙题!!!
考虑一个神奇的转化,把方案求和变成求
i
,
j
i,j
i,j 位置是逆序对的概率
最后的答案就是
2
q
∗
∑
f
i
,
j
2^q*\sum f_{i,j}
2q∗∑fi,j
考虑
f
i
,
j
f_{i,j}
fi,j 为
i
,
j
i,j
i,j 为逆序对的概率
考虑每次交换
x
,
y
x,y
x,y 只会修改
f
x
,
?
,
f
?
,
x
,
f
y
,
?
,
f
?
,
y
f_{x,?},\;f_{?,x},\;f_{y,?},\;f_{?,y}
fx,?,f?,x,fy,?,f?,y,一共
O
(
n
)
O(n)
O(n) 个值
转移可以考虑交换不交换的概率都是
1
2
\frac{1}{2}
21
需要对于
f
x
,
y
,
f
y
,
x
f_{x,y},\;f_{y,x}
fx,y,fy,x 特判,不过这都是细节,主要还是把求和转化为求概率这一关键步骤
时间复杂度
O
(
n
q
)
O(nq)
O(nq)
#include <bits/stdc++.h>
using namespace std;
const int N=3100,P=1e9+7,iv2=500000004;
int n,q,a[N],f[N][N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
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];
for(int i=1;i<=q;i++){
int x=read(),y=read();
for(int i=1;i<=n;i++){
if(i==x||i==y) continue;
int val=(1ll*f[x][i]*iv2+1ll*f[y][i]*iv2)%P;
f[x][i]=f[y][i]=val;
val=(1ll*f[i][x]*iv2+1ll*f[i][y]*iv2)%P;
f[i][x]=f[i][y]=val;
}
int val=(1ll*f[x][y]*iv2+1ll*f[y][x]*iv2)%P;
f[x][y]=f[y][x]=val;
}
int ans=0;
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) ans=(ans+f[i][j])%P;
for(int i=1;i<=q;i++) ans=ans*2%P;
printf("%d",ans);
return 0;
}
/*
f[i][j]:a[i]>a[j]的期望
*/