码迷,mamicode.com
首页 > 其他好文 > 详细

两个常见模型

时间:2019-08-10 00:01:13      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:如何   i+1   常见   推出   复杂   就是   选择   连通   bzoj   

两个常见模型

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的关系:

  1. 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对相邻)
  2. 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]\)
  3. 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]\)的转移方程:

  1. 本来i-1与i-2相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于\(g[i-1][j+1]\),有(j+1-1)种位置可以选(i-1与i-2那对不能拆,因为插入又会形成新的)。
  2. 本来i-1与i-2不相邻,将i插入j对相邻的数的任意一对,这样就破坏了一对,这样方案来源于\(f[i-1][j+1]\),有(j+1)种位置可以选。
  3. 又可能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]了。

两个常见模型

标签:如何   i+1   常见   推出   复杂   就是   选择   连通   bzoj   

原文地址:https://www.cnblogs.com/zhuier-xquan/p/11330013.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!