• 注册
当前位置:1313e > 默认分类 >正文

dtoj#4229. Inverse

题目描述:

小C有一个 $1$ 到 $n$ 的排列 $P$,他会进行 $k$ 次操作,每次等概率选择一段连续区间(每次有 $\frac{n(n+1)}{2}$ 种选择),然后翻转这个区间。

小C想知道 $k$ 次操作后逆序对的期望个数,他觉得这实在是个一眼题,于是这个任务就交给你了。

为了避免精度误差,你只需要输出期望在模 $10^9 + 7$ 意义下的结果。

算法标签:前缀和套前缀和DP优化

思路:

$f[i][j][k]$ 表示 $i,j$ 这两个位置经过 $k$ 次操作,$ai>aj$ 的概率。

第一类:

(区间不覆盖 $i, j$ )
$$
f[i][j][k]+=\sum_{r=1}^{r\le i-1}\sum_{l=1}^{l\le r}f[l][r][k-1]\times P
$$

$$
f[i][j][k]+=\sum_{l=j+1}^{l\le n}\sum_{r=l}^{r\le n}f[l][r][k-1]\times P
$$

总结起来就是:
$$
f[i][j][k]+=f[i][j][k-1]\times P\times (\frac{i\times (i-1)}{2}+\frac{(n-j)\times (n-j+1)}{2}+\frac{(j-i)\times (j-i-1)}{2})
$$


第二类:

(区间只覆盖 $i,j$ 中的一个)
$$
f[i][j][k]+=\sum_{l=1}^{l\le i}\sum_{r=i}^{r\le j-1}f[l+r-i][j][k-1]\times P
$$

当发现 $j$ 是固定的所以对其前缀和
$$
f[i][j][k]+=\sum_{l=1}^{l\le i}(s1[l-i+j-1][j]-s1[l-1][j])\times P
$$
发现第二位仍然是一样的,再进行一次前缀和
$$
f[i][j][k]+=(s2[j-1][j]-s2[j-i-1][j]-s2[i-1][j])\times P
$$

$$
f[j][j][k]+=\sum_{l=i+1}^{l\le r}\sum_{r=j}^{r<=n}f[i][l+r-j][k-1]\times P()
$$

这个式子同上用两次前缀和化简。

第三类:

(区间同时覆盖了 $i, j$ ,意味着两者逆序对的方案数发生变化)
$$
f[i][j][k]+=\sum_{l=1}^{l\le i}\sum_{r=j}^{r\le n}(1-f[l+r-i][l+r-j][k-1])\times P
$$

这类的化简有点不同,发现每一项都在变化,但是发现第一项和第二项的距离不变。

所以考虑令 $g1[i][j]$ 表示f的距离为 $i$ ,第一项为 $j$ 的前缀和。
$$
f[i][j][k]+=P\times (n-j+1)\times i-\sum_{l=1}^{l\le i}(g1[l-i+n][i-j]-g1[l-i+j-1][i-j])
$$
然后就是类似之前的前缀和
$$
f[i][j][k]+=P\times (n-j+1)\times i-g2[n+i-j][j-i]+g2[n-j][j-i]+g2[i-1][j-i]
$$


真可怕......

 以下代码:

#include
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=505,p=1e9+7;
int n,k,a[N],f[N][N],A[N][N],B[N][N],C[N][N],inv;
il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;
}
il int mu(int x,int y){return (x+y>=p)?x+y-p:x+y;
}
il int ksm(LL a,int y){LL b=1;while(y){if(y&1)b=b*a%p;a=a*a%p;y>>=1;}return b;
}
int main()
{n=read();k=read();inv=ksm(n*(n+1)/2,p-2);for(int i=1;i<=n;i++)a[i]=read();for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)f[i][j]=a[i]>a[j];while(k--){for(int j=1;j<=n;j++){for(int i=1;i1][j],f[i][j]);for(int i=1;i1][j],A[i][j]);}for(int i=n;i;i--){for(int j=n;j>i;j--)B[i][j]=mu(f[i][j],B[i][j+1]);for(int j=n;j>i;j--)B[i][j]=mu(B[i][j],B[i][j+1]);}for(int j=0;j){for(int i=1;i<=n-j;i++)C[i][j]=mu(C[i-1][j],f[i][i+j]);for(int i=1;i<=n-j;i++)C[i][j]=mu(C[i][j],C[i-1][j]);}for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){f[i][j]=1ll*f[i][j]*mu(1ll*i*(i-1)/2%p,mu(1ll*(n-j)*(n-j+1)/2%p,1ll*(j-i-1)*(j-i)/2%p))%p;f[i][j]=mu(f[i][j],mu(A[j-1][j],p-mu(A[j-i-1][j],A[i-1][j])));f[i][j]=mu(f[i][j],mu(B[i][i+1],p-mu(B[i][j+1],B[i][n+2-j+i])));f[i][j]=mu(f[i][j],mu(1ll*i*(n-j+1)%p,mu(C[n-j][j-i],mu(C[i-1][j-i],p-C[n+i-j][j-i]))));f[i][j]=1ll*f[i][j]*inv%p;}}}int ans=0;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)ans=mu(ans,f[i][j]);printf("%d\n",ans);return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Jessie-/p/10492421.html

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 162202241@qq.com 举报,一经查实,本站将立刻删除。

最新评论

欢迎您发表评论:

请登录之后再进行评论

登录