UVA1118 Binary Stirling Numbers 题解
题目链接:Binary Stirling Numbers 或者 SP106
题意:
The Stirling number of the second kind $S(n, m)$ represents the number of ways to partition a set of $n$ things into $m$ nonempty subsets. For example, there are seven ways to split a four-element set into two parts:
We can compute $S(n, m)$ using the recurrence,
but your task is slightly different:
给定整数 $n,m$ ,计算出 $S(n,m)$ 的奇偶性,也就是 $S(n,m) \bmod 2$ 。
输入:多组数据,$n,m$ 。输出:答案。
数据范围:
$1 \le m \le n \le 10^9$ 。
首先
那么
可以作图如下(这个图怎么看上去是歪的啊)
图中红线表示 $S(n-1,m-1)$ 到 $S(n,m)$ 的转移,蓝线表示 $S(n-1,m)$ 到 $S(n,m)$ 的转移。
因为只有红线能增加 $m$ ,所以从 $(0,0)$ 到 $(n,m)$ 的转移中,红线经过了 $m$ 次,则蓝线经过了 $n-m$ 次。
而对于点 $(n,m)$ ,能用的蓝线的数量 $k=\left\lfloor\frac{m+1}{2}\right\rfloor$ ,即将 $n-m$ 次蓝线划分为不超过 $k$ 个连续段。
于是问题转化为组合数的奇偶性问题。
根据 Lucas 定理,
这实际上就是在考察 $m$ 的每个二进制位
可以发现,当且仅当 $n,m$ 这一位同时为 $1$ ,答案才可能是 $1$ 。
即,当且仅当 $(n \land m)=m$ ($\land$ 表示二进制按位与) ,$\binom{n}{m} \bmod 2=1$ 。
于是原题就可以做了。
单次询问时间复杂度 $\mathcal{O}(1)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())
void solve()
{
int n, m; cin >> n >> m;
if(!n && !m) { cout << "1\n"; return; }
if(!n || !m || n < m) { cout << "0\n"; return; }
int t = (m + 1) / 2 - 1; cout << ((t & n - m + t) == t) << '\n';
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
int qwq; cin >> qwq; while(qwq--) solve();
return 0;
}
参考文献:
[1] https://www.luogu.com.cn/article/u3g9is8w
[2] https://www.luogu.com.cn/article/7cxxhl0r
题外话: