#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;
}

 

 

 

posted @ 2020-02-12 23:06  xjqxjq  阅读(143)  评论(0编辑  收藏  举报