转自别人的博客。这里记录一下
这题是定义如下的一个数:
S(0, 0) = 1; S(n, 0) = 0 for n > 0;S(0, m) = 0 for m > 0;
S(n, m) = m S(n - 1, m) + S(n - 1, m - 1), for n, m > 0.
也就是题中所说的把一个含有n个元素的集合分成m份,共有多少种分法。
现在题目就是要求S(n, m)的奇偶性。
如果m是一个偶数的话,那么我们可以推出 S(n, m) Ξ S(n-1, m-1) (mod 2),如果m是一个奇数的话,我们推出S(n, m) Ξ (S(n-1, m) + S(n-1, m-1)) (mod 2)。后面看到某一大牛所说的利用画图来推导这个表达式,整了一下,S(n, m)这个状态可由左边的S(n-1, m) 以及 斜下方的 S(n-2, m-2)得到。最后得到结果是c( n-m, n-m+(m-1)/2 ).
最后只要确定一个组合数是否为奇数即可,c(A, B) = B! / (A! * (B-A)!) 我们通过提取上下阶乘的2的个数即可,因为这个式子一定能够约分成整数,那么只要2这个因子没有就一定是一个奇数了。
代码:

#include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> using namespace std; int main() { int T, n, m, t1, t2; scanf("%d", &T); while (T--) { t1 = t2 = 0; scanf("%d %d", &n, &m); if (m == 0 && n) { puts("0"); continue; } n -= m; m = n + (m-1)/2; // n此处就是n-m了 int A = n, B = m, C = (B-A); while (B) { t1 += B/2; B /= 2; } while (A) { t2 += A/2; A /= 2; } while (C) { t2 += C/2; C /= 2; } if (t1 == t2) { puts("1"); } else { puts("0"); } } return 0; }