POJ 1430 Binary Stirling Numbers (排列组合)

题目链接

对于第二类斯特林数S(n,m) = S(n-1,m-1) + m*S(n-1,m),求S(n,m)的奇偶性。

学习了大佬的博客……

在模2的意义下,如果m为偶数,则S(n,m)=S(n-1,m-1);如果m为奇数,则S(n,m)=S(n-1,m-1)+S(n-1,m)。

考虑这种关系的另一种表示:初始时在(0,0)处,对于状态(x,y),如果x为奇数,可以转移到(x+1,y+1)。如果x为偶数,可以转移到(x+1,y+1)和(x+1,y)。定义(x,y)->(x+1,y+1)为a变换,(x,y)->(x+1,y)为b变换。S(n,m)即为变换到(n,m)的方案总数。

可以发现(0,0)到(n,m)必然经过了n次变换,其中有n-m次b变换。且b变换由于只能在偶数处出现,必然是以如下形式:

a,若干次b,a,a,若干次b,a,……,a 

就是说在中间的a必然是连续的,m个a也就是(m+1)/2个间隔。要在(m+1)/2个间隔里放入n-m个b操作,这就是高中数学里著名的(?)隔板法。将n个东西分成m部分,允许某部分为空,方案数为C(n+m-1, m-1)。

也就是说,只需要判断:C(n-m+(m+1)/2-1, (m+1)/2-1)的奇偶性。

另一个结论:当n&m==m时,C(n,m)为奇数,否则为偶数。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1050;
const ll INF = (1LL << 62) - 1;
const ll mod = 998244353;
const double eps = 1e-8;

int t;
ll n, m;

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%lld%lld", &n, &m);
        if(n == 0 && m == 0) {printf("1\n"); continue;}
        if(n == 0 || m == 0 || n < 0) {printf("0\n"); continue;}
        ll a = n - m, b = (m + 1)/2;
        if(((a+b-1) & (b-1)) == (b-1)) printf("1\n");
        else printf("0\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/82802685