#4229. Inverse
题目描述
小C有一个 $1$ 到 $n$ 的排列 $P$,他会进行 $k$ 次操作,每次等概率选择一段连续区间(每次有 $\frac{n(n+1)}{2}$ 种选择),然后翻转这个区间。
小C想知道 $k$ 次操作后逆序对的期望个数,他觉得这实在是个一眼题,于是这个任务就交给你了。
为了避免精度误差,你只需要输出期望在模 $10^9 + 7$ 意义下的结果。
题解
考虑 $(i,j)$ 的贡献,于是设计dp: $f[i][j][k]$ 表示 $(i,j)$ 在 $k$ 轮之后 $p_i>p_j$ 的概率, $g[i][j][k]$ 表示 $p_i<p_j$的概率,其中 $i<j$ 。
考虑 $f$ 的转移,假设第 $k$ 轮翻转 $[l,r]$ ,设 $U=\frac{2}{n(n-1)}$ ,分类一下:
1. $l \in [1,i],r \in [i,j)$ ,贡献为 $U \times f[l+r-i][j][k-1]$ ;
2. $l \in (i,j],r \in [j,n]$ ,贡献为 $U \times f[i][l+r-j][k-1]$ ;
3. $l \in (i,j),r \in (i,j) || l \in (j,n] || r \in [1,i)$ ,贡献为 $U \times f[i][j][k-1]$ ;
4. $l \in [1,i],r \in [j,n]$ ,贡献为 $U \times g[l+r-j][l+r-i][k-1]$ 。
$g$ 的转移是类似的。
对于前两个来说,我们发现有一维是固定的,所以另一维做二次前缀和即可,对于第四个来说,我们发现它的差是固定的,所以对于差我们做二次前缀和即可,因此效率为 $O(n^2k)$
代码
#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; }