[AT2062] ~K Perm Counting

问题描述

求长度为n的排列满足\(|p[i]-i|\not =k\)
n,k<=2000

解析

可以用棋盘的方法来解决这道问题。对于条件\(|p[i]-i|\not =k\),我们可以画出如下的棋盘图:

那么要求就是不能有点放在黑点上。可以用总方案数减去不合法方案数。而不合法方案数可以用容斥来计算,式子如下:

\[\sum(-1)^i\times F[i]\times (n-i)! \]

\(F[i]\)表示的是有\(i\)个点放在黑点上的方案数。其余的点可以随便放,只要满足不同行且不同列即可,所以方案为\((n-i)!\) 。那么,怎么求\(F [i]\)呢?

通过上图可以发现,如果选择了一个黑点,跟他同行同列的黑点都不能再被选择。继续观察,发现所有的矛盾关系构成几条互不干扰的链,就像下图所示:

那么,在每一条链上都不能选择相邻的点。不同的链可以拼在一起,只允许相连接的地方可以相邻。这就是一个DP了。设\(f[i][j][0/1]\)表示当前在第\(i\)位、选了\(j\)个点、第\(j\)个点左边相邻的点有没有选的方案数。最后有

\[F[i]=f[len][i][0]+F[len][i][1] \]

\(len\) 表示链长之和。

代码

咕了

posted @ 2020-01-16 22:28  CJlzf  阅读(144)  评论(0编辑  收藏  举报