题解:P14654 夤生月

· · 题解

题意

排列连边必然形成若干个简单环;排列的权值定义说明(求 G 时)我们只需要关心每个环内有哪些数。故题目实际上为:

  1. 1...n 放进 m 个置换环里,问方案数;
  2. 1...n 放进 m 个集合里,问方案数。

换句话说,分别求第一类斯特林数和第二类斯特林数在模 2 意义下的值,要求 O(1)

题解

关于斯特林数的推导这里不再赘述。考虑第一类斯特林数的递推式:

\begin{bmatrix}n\\ k\end{bmatrix}=\begin{bmatrix}n-1\\ k-1\end{bmatrix}+(n-1)\begin{bmatrix}n-1\\ k\end{bmatrix}

由于模数为 2,有简单转化:

\begin{bmatrix}n-1\\ k-1\end{bmatrix}+\begin{bmatrix}n-1\\ k\end{bmatrix}, & 2\mid n, \\ \begin{bmatrix}n-1\\ k-1\end{bmatrix}, & 2\nmid n. \end{cases}

不妨令 n 为偶数,则有:

\begin{bmatrix}n\\ k\end{bmatrix}=\begin{bmatrix}n-2\\ k-2\end{bmatrix}+\begin{bmatrix}n-2\\ k-1\end{bmatrix}

其中,\begin{bmatrix}0\\ 0\end{bmatrix} = 1

考虑一张这样的图:

$${n\choose m}\equiv [n\&m=m]\pmod 2$$ 容易做到 $O(1)$。 第二类斯特林数与之类似,其推导出的式子为: $$ \begin{Bmatrix}n\\ k\end{Bmatrix}=\begin{Bmatrix}n-2\\ k-2\end{Bmatrix}+\begin{Bmatrix}n-1\\ k\end{Bmatrix} $$ 注意此时我们令 $k$ 为奇数。 ## Code ```cpp #include<bits/stdc++.h> using namespace std; int q; inline int C(int a,int b) { return (a&b) == b; } signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin >> q; while (q--) { int op,n,m; cin >> op >> n >> m; if (n < m) cout << 0; else if (op == 1) { if (n&1) n--,m--; int l = n/2; cout << C(l,m-l); } else { if (!(m&1)) n--,m--; int l = (m-1)/2; cout << C(n-1-l,l); } } return 0; } ```