错排问题:不能错这么多
Background
P6174 这篇错排推导非常有趣,然后里面有个 point 是当想要把 \(n\) 号球放进 \(k\) 号箱子的时候,分成两种情况讨论:\(n\) 号箱子里装的是或者不是 \(k\) 号球。在这里,错排求的方案数是 限制某个箱子不能装某个球,求可行的把球放进箱子,每个箱子里装的是一个的方案数。那么,\(n\) 号箱子装 \(k\) 号球,\(k\) 号箱子装 \(n\) 号球这个相互放 fact 非常的有意思,通过这个玩法我们将子问题 \(D_n\) 缩小到了子问题 \(D_{n-2}\)。
令最后盒子 \(i\) 中装的球为 \(\mathrm{box}[i]\),在原版的问题中显然不合法的条件为存在 \(\mathrm{box}[i]=i\),即箱子 \(i\) 不能装 \(i\) 号球。那么如果拓展一下问题,把它反转过来,现在我们求正确的放置方案有多少种。显然,一种:对于 \(\forall i \in [1,n]\) 有 \(\mathrm{box[i]}=i\)。那我们放宽一点要求,\(\mathrm{box}[\mathrm{box}[i]]=i\),即沿着盒子里球的编号去找另一个盒子里的球找到了,也可以接受,有多少种方案?如果 \(\mathrm{box}[\mathrm{box}[\mathrm{box}[i]]]=i\) 也可以接受呢?如果 \(\mathrm{box}[\mathrm{box}[\mathrm{box}[\mathrm{box}[i]]]]\) 也可以接受呢?令 \(\mathrm{box}^\mathrm{step}[i]\) 表示访问多少层 \(\mathrm{box}\),如上述分别为 \(\mathrm{step}=\{1,~2,~3,~4\}\),如果 \(\forall i \in [1,\mathrm{step}]\), \(\mathrm{box}^\mathrm{step}[i]\) 都可以接受呢?
Solution
这个问题起点在于缩小子问题的这个过程:当然我们考虑局部合法的情况时,首先,显然,把 \(k\) 球放入箱子 \(k\) 是一个 \(\mathrm{step}=1\) 的情形;而当我们选择球 \(k\) 和另一个箱子 \(p~(k\neq p)\) 时,如果 \(k\) 球放入了 \(p\),\(p\) 球放入了 \(k\),显然就成功构造了一个 \(\mathrm{step}=2\) 的情形。那么可接受的方案有多少种呢?\(n=1\) 时不存在 \(\mathrm{step}=2\) 而必定 \(1\) 号球入 \(1\) 号箱子,一种。\(n=2\) 时 \(1,2\) 和 \(2,1\) 都可以接受,分别是 \(\mathrm{step}\) 为 \(1\) 和 \(2\) 的情形,两种。\(n=3\) 呢?选一个球,然后再选另一个球(\(n-1\) 种选法),这两个球交错插入对方的箱子,此时两个箱子里的球都可以以 \(\mathrm{step}=2\) 被接受,问题变成剩下一个箱子求方案数;又或是这个球插入自己的箱子,这个球以 \(\mathrm{step}=1\) 被接受,求剩下两个箱子的方案数。这样分解问题的一个原因是,当一个大小不超过 \(\mathrm{step}\) 的箱子集合 \(S\) 里的球的集合 \(S'=S\) 时,\(S\) 中的任意一个箱子总能在 \(S\) 中找到和自己编号一致的球,而 \(S\) 外的任意一个箱子不会找到 \(S\) 中的箱子,所以我们可以 drop 掉这几个箱子和球,求解子问题。若设 \(\mathrm{dp}[i]\) 表示剩下 \(n\) 个球(箱子)时的方案数,即有 \(\mathrm{dp}[3]=\mathrm{dp}[3-2]\cdot (3-1)+\mathrm{dp}[3-1]=4\) 种。此时能发现,我们总能将球数为 \(n\) 的问题分解为 \(n'=n-2\) 和 \(n'=n-1\) 的子问题并合并答案。递推式为:
当 \(\mathrm{step}=3\) 呢?此时,在 \(\mathrm{step}=2\) 的基础之上,我们选择三个箱子 \(p, q, r\)(\((n-1)\cdot (n-2)\) 个选法),使得 \(\mathrm{box}[p]=q, \mathrm{box}[q]=r, \mathrm{box}[r]=p\),此时多分解出一个 \(n'=n-3\) 的子问题
而 \(\mathrm{step}=4\) 则有
对于任意 \(1<\mathrm{step}\le n,\mathrm{step}\in Z\),可能有(未证,猜想有):
Code
写得非常暴力的一个版本,有空再改,包含了对拍和求解
#include <cstdio>
int box[15],ans=0,tot=0;bool used[15];
int n, foo[15], dp[15];
void search(int now){
if(now>n) {
tot++;
for(int i=1;i<=n;i++)
if(!(box[i]==i || box[box[i]]==i || box[box[box[i]]]==i || box[box[box[box[i]]]]==i)) return;
ans++;
for(int i=1;i<=n;i++)
printf("%d ",box[i]);
printf("\n");
return;
}
for(int i=1;i<=n;i++)
if(!used[i])
{
box[now]=i;
used[i]=1;
search(now+1);
used[i]=0;
}
}
int main() {
for(int i=1;i<=10;i++) {
ans = 0; tot=0;
n=i;
search(1);
foo[i]=ans;
}
dp[1]=1;dp[2]=2;dp[3]=6;dp[4]=24;
for(int i=5;i<=10;i++) {
dp[i]=dp[i-4]*(i-3)*(i-2)*(i-1)+dp[i-3]*(i-1)*(i-2)+dp[i-2]*(i-1)+dp[i-1];
printf("%d %d %d %s\n",i,dp[i],foo[i],dp[i]==foo[i]?"YES":"NO");
}
return 0;
}
Question
\(\mathrm{step}\) 起点可以选择吗?可以中间少几个吗?即,这几个 \(\mathrm{step}\) 不合法的情况下能算吗:
- \(2,3,4\)
- \(1,2,4\)
* 最佳答案:我不知道
在声明禁止转载的情况下,请勿转载;若本文章为转载的文章,版权归原作者所有。
如果您觉得本文写得好,请点击下方的推荐按钮~若您有任何建议和指正,请在下方留言,对于您的指正将不胜感激。