[数据丢失]围坐问题 Menage数

壹、题目描述 ¶

见 BZOJ P30181 Seat.

题目

有一张圆形的餐桌,这张餐桌有 \(2n\) 个座位。现在有 \(n\) 对夫妻就坐,要求男士和女士隔位就坐,并且每对夫妻不能相邻,求安排座位的方案数,答案对 \(998244353\) 取模。

数据范围与提示

保证 \(3\le n\le 10^5\),没有任何提示 😃

注意,由于是一个圆形的餐桌,所以经过旋转变换得到的坐法相同则认为是同一种方案。

贰、题解 ¶

我们首先可以考虑将女士安置好,不难发现 \(n\) 个女士构成圆排列,方案数为 \((n-1)!\),接下来考虑男士的坐法。

但是似乎不同的女士的坐法,会影响男士的可行坐法方案数?事实上,并非如此,考察下列问题:


有一个数列,共有 \(n\) 位,现要将 \(1,2,3,\cdots n\) 放入这 \(n\) 位中,对于每个位置有个要求,必须保证 \(a_i\neq p_i\),且 \(p_i\) 两两不同,求方案数?

不难发现,该问题的方案数即 \(D(n)\),由于每一位都是独立的,我们可以考虑将 \(p_i=1\)\(i\) 放到第一位,将 \(p_j=2\)\(j\) 放到第二位......然后问题即变为:在 \(n\) 个位置上放数,必须有 \(a_i\neq i\),这就是经典错排模板。故而,即使这个 \(p\) 怎么变,在方案数上,总是与最经典的错排问题方案数是相同的。


该问题也是同样的,无论女士怎样坐,男士落座的方案数都与 “第一个女士坐第一位,第二个女士坐第二位......” 的方案数相同,因此我们将这个问题进行了简化,我们可以不用在意女士具体应当是怎样坐,我们只将他们当成最简单的情形(上述)。接下来考虑在该情形下男士落座的方案。

由于第 \(i\) 个女士左右都不能放第 \(i\) 个男士,又因为我们已经将情形简化,故而此时,我们可以认为第 \(i\) 个女士的右边不能坐第 \(i\) 个或者第 \((i+1)\bmod n\) 个男士(如果它右边坐第 \((i+1)\bmod n\) 个男士,就相当于下一个女士(第 \((i+1)\bmod n\) 的女士)的左边坐了第 \((i+1)\bmod n\) 个男士,这是不合法的),我们考虑设 \(p_i\) 表示第 \(i\) 个女士的右边坐下了第 \(i\)\((i+1)\bmod n\) 个男士,接下来我们想要求的就是

\[|U|-\left|\bigcup_{i=1}^np_i\right| \]

有了该式子,我们不难往容斥方向想,考虑枚举有多少个女士满足了自己的 \(p_i\) 性质,那么可以得到下列式子:

\[Ans'=\sum_{k=0}^n(-1)^kF(k) \]

关于这个 \(F(k)\) 应该如何选择?考虑这个 \(F(k)\) 的组合意义:有 \(k\) 个女士满足自身 \(p_i\) 性质,剩下的 \(n-k\) 个女士右边随便坐的方案数。

后者即为 \((n-k)!\),这很好办,但是前者?我们不妨将所有女士想要满足自己 \(p_i\) 性质的男士编号写成一排(同一个女士的限制写在一个括号中),那么可以得到:

\[(12)(23)(34)(45)\cdots {\large(}(n-1)n{\large)}(n1) \]

对于这个序列,我们要选出 \(k\) 个数,要求有:

  • 同一个数不能被选择两次(相当于一个男士同时坐在两个女士右边请务必让我来承受这般酷刑);
  • 不能同时选择同一个括号中的两个数,这相当于一个女士右边坐了两个男士(?);

如果我们将括号撇去不看,还是上面俩限制,那么,这就相当于:从围成一圈(因为头尾都是 \(1\))的 \(2n\) 个球中选出 \(k\)不相邻的球的方案数,共 \(2n\) 个球,故方案数即为 \({2n\over 2n-k}{2n-k\choose k}\),所以容斥式子即为:

\[Ans'=\sum_{k=0}^n(-1)^k{2n\over 2n-k}{2n-k\choose k}(n-k)! \]

该式子得到的数又被称为 \(\rm Menage\) 数。

最后的答案 \(Ans=(n-1)!\times Ans'\),因为我们从始至终都将女士坐法当成 \(1,2,3,4,\cdots\) 来看,但是女士坐法也是可以变化的。


组合式 \({2n\over 2n-k}{2n-k\choose k}\) 是怎么得到的?

我们先考虑一个简单的情形 —— 从一排(并非一个圈)\(n\) 个球中选出 \(k\) 个互不相邻的出来,方案数?

分两种情况讨论:

  • \(n<2k-1\) 时,无合法方案;
  • \(n\ge 2k-1\) 时,我们可以考虑拿出 \(k-1\) 个球当成 \(k\) 个球的强制隔板,然后我们从剩下 \(n-k+1\) 个球中随便选 \(k\) 个出来就行了,不难发现方案数就是 \({n-k+1\choose k}\),由于所有球都是相同的,

接下来,我们分析 \(n\) 个球围成一个圈的问题:

  • \(n<2k\) 时,无合法方案;
  • \(n\ge 2k\) 时,考虑破环成链 —— 选择 \(1\) 号球与不选 \(1\) 号球;
    • 如果选择了第 \(1\) 个球,那么就相当于从 \(3\sim n-1\) 中选出 \(k-1\) 个不相邻的球,套用上文结论,方案数 \({n-k-1\choose k-1}\)
    • 如果没选择第 \(1\) 个球,相当于从 \(2\sim n\) 中选出 \(k\) 个不相邻的球,方案数 \({n-k\choose k}\)

总方案数即为

\[{n-k-1\choose k-1}+{n-k\choose k}={n{n-k\choose k}\over n-k} \]

这就得到上文的式子。

残留问题:

\(k\) 阶错排怎么搞?

预备知识:棋盘多项式等......


总时间复杂度 \(\mathcal O(\;n\log \bmod)\),由于使用了费马小定理求逆元。但是应该可以不用。

叁、参考代码 ¶

const int maxn=2e5;
const int mod=998244353;

inline int qkpow(int a, int n){
    int ret=1;
    for(; n>0; n>>=1, a=1ll*a*a%mod)
        if(n&1) ret=1ll*ret*a%mod;
    return ret;
}

int fac[maxn+5], finv[maxn+5];
inline void prelude(){
    finv[0]=fac[0]=1;
    rep(i, 1, maxn) fac[i]=1ll*fac[i-1]*i%mod;
    finv[maxn]=qkpow(fac[maxn], mod-2);
    drep(i, maxn-1, 1) finv[i]=1ll*finv[i+1]*(i+1)%mod;
}
inline int C(int n, int m){
    if(n<m || n<0 || m<0) return 0;
    return 1ll*fac[n]*finv[m]%mod*finv[n-m]%mod;
}

int n;
#define sign(i) (((i)&1)? -1: 1)
signed main(){
    prelude(); n=readin(1);
    int ans=0;
    rep(k, 0, n)
        ans=(ans+1ll*sign(k)*2*n*qkpow(2*n-k, mod-2)%mod*C(2*n-k, k)%mod*fac[n-k]%mod)%mod;
    ans=(ans+mod)%mod;
    writc(1ll*ans*fac[n-1]%mod);
    return 0;
}

肆、关键之处 ¶

在恰当的地方对问题进行简化,或者将比较复杂的情形与一般情形建立关系。

posted @ 2021-08-17 09:08  Arextre  阅读(287)  评论(0编辑  收藏  举报