题目描述
小C有一个 1 1 1 到 n n n 的排列 P P P,他会进行 k k k 次操作,每次等概率选择一段连续区间(每次有 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1) 种选择),然后翻转这个区间。
小C想知道 k k k 次操作后逆序对的期望个数,他觉得这实在是个一眼题,于是这个任务就交给你了。
为了避免精度误差,你只需要输出期望在模 1 0 9 + 7 10^9 + 7 109+7 意义下的结果。
题解
考虑 ( i , j ) (i,j) (i,j) 的贡献,于是设计dp: f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k] 表示 ( i , j ) (i,j) (i,j) 在 k k k 轮之后 p i > p j p_i>p_j pi>pj 的概率, g [ i ] [ j ] [ k ] g[i][j][k] g[i][j][k] 表示 p i < p j p_i<p_j pi<pj的概率,其中 i < j i<j i<j 。
考虑 f f f 的转移,假设第 k k k 轮翻转 [ l , r ] [l,r] [l,r] ,设 U = 2 n ( n − 1 ) U=\frac{2}{n(n-1)} U=n(n−1)2 ,分类一下:
- l ∈ [ 1 , i ] , r ∈ [ i , j ) l \in [1,i],r \in [i,j) l∈[1,i],r∈[i,j) ,贡献为 U × f [ l + r − i ] [ j ] [ k − 1 ] U \times f[l+r-i][j][k-1] U×f[l+r−i][j][k−1] ;
- l ∈ ( i , j ] , r ∈ [ j , n ] l \in (i,j],r \in [j,n] l∈(i,j],r∈[j,n] ,贡献为 U × f [ i ] [ l + r − j ] [ k − 1 ] U \times f[i][l+r-j][k-1] U×f[i][l+r−j][k−1] ;
- l ∈ ( i , j ) , r ∈ ( i , j ) ∣ ∣ l ∈ ( j , n ] ∣ ∣ r ∈ [ 1 , i ) l \in (i,j),r \in (i,j) || l \in (j,n] || r \in [1,i) l∈(i,j),r∈(i,j)∣∣l∈(j,n]∣∣r∈[1,i) ,贡献为 U × f [ i ] [ j ] [ k − 1 ] U \times f[i][j][k-1] U×f[i][j][k−1] ;
- l ∈ [ 1 , i ] , r ∈ [ j , n ] l \in [1,i],r \in [j,n] l∈[1,i],r∈[j,n] ,贡献为 U × g [ l + r − j ] [ l + r − i ] [ k − 1 ] U \times g[l+r-j][l+r-i][k-1] U×g[l+r−j][l+r−i][k−1] 。
g g g 的转移是类似的。
对于前两个来说,我们发现有一维是固定的,所以另一维做二次前缀和即可,对于第四个来说,我们发现它的差是固定的,所以对于差我们做二次前缀和即可,因此效率为 O ( n 2 k ) O(n^2k) O(n2k)
代码
#include <bits/stdc++.h>
using namespace std;
const int N=505,P=1e9+7;
int f[2][N][N],g[2][N][N][3],h[2][N][N][3],s[2][N][N][3],a[N],n,m,V,ans,F[2][N][N];
inline int X(int x){return x>=P?x-P:x;}
int K(int x,int y){
int z=1;
for (;y;y>>=1,x=1ll*x*x%P)
if (y&1) z=1ll*z*x%P;
return z;
}
inline int H(int i,int j,int o){
int u,v,x,y;
v=1ll*h[o][j-1][j][2]*i%P;
x=X(h[o][i][j][1]-1ll*h[o][i][j][2]*(n-i)%P+P);
y=X(X(h[o][j-1][j][0]-h[o][j-i-1][j][0]+P)-1ll*(h[o][j-1][j][2]-h[o][j-i-1][j][2]+P)*(j-i)%P+P);
u=X(v+P-X(x+y));
v=1ll*g[o][i][n][2]*(j-i)%P;
x=X(g[o][i][j][1]-1ll*g[o][i][j][2]*(n-j)%P+P);
y=X(X(g[o][i][n][0]-g[o][i][n+i-j][0]+P)-1ll*(g[o][i][n][2]-g[o][i][n+i-j][2]+P)*(n+i-j+1)%P+P);
u=X(u+X(v+P-X(x+y)));
o^=1;
v=1ll*s[o][n+i-j][j-i][2]*i%P;
x=X(1ll*s[o][i][j-i][1]-1ll*s[o][i][j-i][2]*(n-i)%P+P);
y=X(X(s[o][n+i-j][j-i][0]-s[o][n-j][j-i][0]+P)-1ll*(s[o][n+i-j][j-i][2]-s[o][n-j][j-i][2]+P)*(n-j+1)%P+P);
return X(u+X(v+P-X(x+y)));
}
int main(){
cin>>n>>m;V=X(K(n*(n+1),P-2)<<1);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
f[a[i]<a[j]][i][j]=1;
for (int k=1;k<=m;k++){
for (int o=0;o<2;o++)
for (int i=1;i<=n;i++){
for (int j=i+1;j<=n;j++)
g[o][i][j][0]=X(g[o][i][j-1][0]+1ll*j*f[o][i][j]%P),
g[o][i][j][1]=X(g[o][i][j-1][1]+1ll*(n-j)*f[o][i][j]%P),
g[o][i][j][2]=X(g[o][i][j-1][2]+f[o][i][j]),
s[o][i][j-i][0]=X(s[o][i-1][j-i][0]+1ll*i*f[o][i][j]%P),
s[o][i][j-i][1]=X(s[o][i-1][j-i][1]+1ll*(n-i)*f[o][i][j]%P),
s[o][i][j-i][2]=X(s[o][i-1][j-i][2]+f[o][i][j]);
for (int j=1;j<i;j++)
h[o][j][i][0]=X(h[o][j-1][i][0]+1ll*j*f[o][j][i]%P),
h[o][j][i][1]=X(h[o][j-1][i][1]+1ll*(n-j)*f[o][j][i]%P),
h[o][j][i][2]=X(h[o][j-1][i][2]+f[o][j][i]);
}
for (int o=0;o<2;o++){
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
f[o][i][j]=1ll*(h[o][i][j][2]-h[o][i-1][j][2]+P)*(((j-i-1)*(j-i)+(i-1)*i+(n-j)*(n-j+1))>>1)%P,
f[o][i][j]=1ll*V*X(f[o][i][j]+H(i,j,o))%P;
}
}
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
ans=X(ans+f[0][i][j]);
cout<<ans<<endl;return 0;
}