两个常见模型
Posted zhuier-xquan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两个常见模型相关的知识,希望对你有一定的参考价值。
两个常见模型
bzoj4321
编号为1~n的人排成一排,问有多少种排法使得任意相邻两人的编号之差不为1或-1。
n<=1000
破坏空位:有两个相邻的之间
我们设\(f[i][j]\)表示1~i的排列,有j组相邻的相差1,且i和i-1不相邻的方案数;
我们设\(g[i][j]\)表示1~i的排列,有j组相邻的相差1,且i和i-1相邻的方案数;
考虑插入i+1的位置,有:
不破坏空位且不与 i 相邻、不破坏空位且与 i 相邻、破坏空位且不与 i 相邻、破坏空位且与 i 相邻(只发生在 g 的转移) 4种。
分别推一下方案数:
首先考虑i和i-1相邻的方案数:
我们考虑一下i-2,i-1和i的关系:
- i-1与i-2相邻,然后我们将i放在i-1与i-2的中间:这样将i-1,i-2这一对相邻拆开了,但是又增加了i和i-1这一对,所以相邻的个数相当于没增也没减,也就是\(g[i][j]\)有一项是从\(g[i-1][j]\)转移过来的(前i-1个数,i-1和i-2相邻,共有j对相邻)
- i-1与i-2相邻,但是i不放在i-1与i-2的中间,而放在i-1的另一侧:这样我们没有破坏i-1和i-2这一对相邻,并且新增加了i-1和i这一对相邻,因此相邻数增加了1,转移后是j,那么转移前应该是j-1:\(g[i-1][j-1]\)
- i-1与i-2不相邻:那么我们也就可以将i放在i-1的一侧,这样增加一对相邻,由于可以将i放在i-1左右两边共两种情况,所以:\(f[i-1][j-1]*2\)因为i-1和i-2不相邻嘛,所以用f;
\(g[i][j]=g[i-1][j]+g[i-1][j-1]+f[i-1][j-1]*2\)
同理可以推出\(f[i][j]\)的转移方程:
- 本来i-1与i-2相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于\(g[i-1][j+1]\),有(j+1-1)种位置可以选(i-1与i-2那对不能拆,因为插入又会形成新的)。
- 本来i-1与i-2不相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于\(f[i-1][j+1]\),有(j+1)种位置可以选。
- 又可能i不去拆开相邻的数,就可以来源于 \(g[i-1][j]\)*(i-j-1)(可以插入i-1与i-2,不改变对数) 或 \(f[i-1][j]\)*(i-j-2)
\(f[i][j]=g[i-1][j+1]*j+f[i-1][j+1]*(j+1)+g[i-1][j]*(i-j-1)+f[i-1][j]*(i-j-2)\)
最后的答案就是\(f[n][0]\)
时间复杂度 O(n^2) 。
BZOJ2560 串珠子
有n个珠子,第i和j个珠子之间有\(c[i][j]\)条不同的绳子可选。每对珠子之间可以选择不连绳子,也可以选择用其中一种绳子连接。
问有多少种方案能使n个珠子成为连通图。
n<=16
连通图计数套路: 用总数减去不连通的方案数,而不连通的方案数,可以枚举1号点所在连通块的点集(有的问题中是大小) ,用这个点集的连通方案数乘以剩余点集的总方案数即可。???
我们设两个数组,g[s]表示s状态下的所有情况,即s状态下的点两两之间任意连边(包括不连边的情况),f[s]表示s状态下的合法情况,即使得s状态下所有点连通的合法情况。那么答案就是f[2^n-1]。
\(g[s]=g[s-(1<<i)]+\sum_j\in s-(i<<i)[i][j]\) \(O(n*2^n)\)
然后我们可以很容易地求出g[s],我们求出g[s]后,考虑如何求f[s],f[s]就是g[s]减去所有的不合法情况。那么我们可以枚举s的所有子集,设子集为i,那么不合法的情况就是g[i]*f[s^i],我们减去这些情况,就能求出f[s]了。
以上是关于两个常见模型的主要内容,如果未能解决你的问题,请参考以下文章