poj 1430 Binary Stirling Numbers
这是一道组合数学题:
首先由于%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)。
要想(0,0)到(n,m)一定要是从(1,1),因为从n轴不能经过,因为S(n, 0) = 0,那么从(1,1)到(n,m)横轴要走n-m步,纵轴要走m-1格,由于每次走2格,因此只要走(m-1)/2步;

#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; }