poj 1430 Binary Stirling Numbers

这是一道组合数学题:


poj 1430 Binary Stirling Numbers_第1张图片

首先由于%2的操作,我想到了f(n,m) = s(n,m)%2,假设一个f函数。于是s(n,m) = m * s(n-1,m)+ s(n-1,m-1) ==>
f(n,m) = s(n-1,m-1) (m为偶数); f(n,m) = f(n-1,m) + f(n-1,m-1)=f(n-1,m)+f(n-2,m-2)(m为奇数,则m-1为偶数)。这样就可以将m给去掉,最后就是计算f(n,m)%2即可,必须想到怎么样得到
f(n,m)。
 
怎么得到呢?这一步是比较难想的。我用递推,推了很久都不行,因为n,m实在太大了。于是我想到了先画个图,希望通过图形来表示它们的递推关系,果真很管用,我找到了。x轴表示n方向,y轴表示m方向,那么我可以看出其实就找从(0,0)点到(n,m)点有多少条路径,就是f(n,m) 的值了。如果大家将图画出来后,然后通过上式去找,我相信会找到公式了,最后其实得到的是一个组合 求出 f(n,m) = C(n-m, (m-1)/2)。

poj 1430 Binary Stirling Numbers_第2张图片

要想(0,0)到(n,m)一定要是从(1,1),因为从n轴不能经过,因为S(n, 0) = 0,那么从(1,1)到(n,m)横轴要走n-m步,纵轴要走m-1格,由于每次走2格,因此只要走(m-1)/2步;

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
#include<string>
#define LL long long
using namespace std;
int Get_num2( int x )
{
    if( x == 0 ) return 0;
    return x/2 + Get_num2( x/2 );    
}
int main(  )
{
    int n,m,T;
    while( scanf( "%d",&T )==1 )
    {
        while( T-- )
        {
            scanf( "%d %d" ,&n,&m ); 
            int num2 = Get_num2( n - m + ( m -1 )/2 ) -Get_num2( n - m ) - Get_num2( (m-1)/2 );
            if( num2 > 0 )
                puts( "0" );
            else puts( "1" );    
        }
    }
    //system( "pause" );
    return 0;
}

 

你可能感兴趣的:(number)