C - Binary Stirling Numbers解题报告(来自网络)
2012-04-17 19:40
393 查看
C - Binary Stirling Numbers
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice POJ
1430
Description
The Stirling number of the second kind S(n, m) stands for 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:
There is a recurrence which allows to compute S(n, m) for all m and n.
Your task is much "easier". Given integers n and m satisfying 1 <= m <= n, compute the parity of S(n, m), i.e. S(n, m) mod 2.
Example
Task
Write a program which for each data set:
reads two positive integers n and m,
computes S(n, m) mod 2,
writes the result.
Input
The first line of the input contains exactly one positive integer d equal to the number of data sets, 1 <= d <= 200. The data sets follow.
Line i + 1 contains the i-th data set - exactly two integers ni and mi separated by a single space, 1 <= mi <= ni <= 10^9.
Output
The output should consist of exactly d lines, one line for each data set. Line i, 1 <= i <= d, should contain 0 or 1, the value of S(ni, mi) mod 2.
Sample Input
Sample Output
过了这题,我很兴奋,很久都没有这种感觉了。真的很舒服,不过这题我想了很久,数论的类型,的确有些难想。
好了,不多说了,说说这题到底怎么个解法吧!此题解法都是自己一步一步推过来的,希望对大家有启发。
首先由于%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)(m为奇数)。这样就可以将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)。不会很难找,大家就画画吧。
简化就是求C(n,m)%2 ,就是求C(n,m)的奇偶了。怎么求呢,这又是一个难点。C(n,m) = m!/(n!*(m-n)!){这个大家都知道的},这里就是要靠数学感觉了,我直接就想到了肯定和2因子有关,于是就得到这样一个结论,如果分子2因子的个数= 分母2因子的个数,那么就为奇数;否则就为偶数.。大家多想想,如果有些疑问,给我留言,现在就不在这里多说了。
相信大家如果看来上面且明白后,这个题AC就是2分钟内了。
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice POJ
1430
Description
The Stirling number of the second kind S(n, m) stands for 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:
{1, 2, 3} U {4}, {1, 2, 4} U {3}, {1, 3, 4} U {2}, {2, 3, 4} U {1} {1, 2} U {3, 4}, {1, 3} U {2, 4}, {1, 4} U {2, 3}.
There is a recurrence which allows to compute S(n, m) for all m and n.
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.
Your task is much "easier". Given integers n and m satisfying 1 <= m <= n, compute the parity of S(n, m), i.e. S(n, m) mod 2.
Example
S(4, 2) mod 2 = 1.
Task
Write a program which for each data set:
reads two positive integers n and m,
computes S(n, m) mod 2,
writes the result.
Input
The first line of the input contains exactly one positive integer d equal to the number of data sets, 1 <= d <= 200. The data sets follow.
Line i + 1 contains the i-th data set - exactly two integers ni and mi separated by a single space, 1 <= mi <= ni <= 10^9.
Output
The output should consist of exactly d lines, one line for each data set. Line i, 1 <= i <= d, should contain 0 or 1, the value of S(ni, mi) mod 2.
Sample Input
1 4 2
Sample Output
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)(m为奇数)。这样就可以将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)。不会很难找,大家就画画吧。
简化就是求C(n,m)%2 ,就是求C(n,m)的奇偶了。怎么求呢,这又是一个难点。C(n,m) = m!/(n!*(m-n)!){这个大家都知道的},这里就是要靠数学感觉了,我直接就想到了肯定和2因子有关,于是就得到这样一个结论,如果分子2因子的个数= 分母2因子的个数,那么就为奇数;否则就为偶数.。大家多想想,如果有些疑问,给我留言,现在就不在这里多说了。
相信大家如果看来上面且明白后,这个题AC就是2分钟内了。
#include <iostream> using namespace std; __int64 f(__int64 x)//计算x! 2的因子数目 { __int64 t =0; while(x) { x /= 2; t += x; } return t; } int main() { int cas; __int64 n,m; scanf("%d",&cas); while(cas) { cas --; cin>>n>>m; n -= m; m = (m-1)/2; if(f(n+m) == f(n)+ f(m)) printf("1\n"); else printf("0\n"); } return 0; }
相关文章推荐
- F - Dividing解题报告(来自网络)
- I - An Easy Problem!解题报告(来自网络)
- B - Run Away解题报告(来自网络)
- N - TOYS解题报告(来自网络)
- F - Summits解题报告(来自网络)
- G - Islands and Bridges解题报告(来自网络)
- A - Wall解题报告(来自网络)
- C - How I Mathematician Wonder What You Are!解题报告(来自网络)
- E - Pipe解题报告(来自网络)
- D - Magic Bracelet解题报告(来自网络)
- E - Biorhythms解题报告(来自网络)
- 【LeetCode】95.Unique Binary Search Trees II(Medium)解题报告
- HDOJ-1905-Pseudoprime numbers 解题报告
- Add Two Numbers | LeetCode OJ 解题报告
- [leetcode] 110. Balanced Binary Tree 解题报告
- 【九度OJ】题目1442:A sequence of numbers 解题报告
- LeetCode Convert Sorted List to Binary Search Tree 解题报告
- 【LeetCode】226. Invert Binary Tree 解题报告
- zsacm第一期网络练习解题报告
- 【原】 POJ 2739 Sum of Consecutive Prime Numbers 筛素数+积累数组 解题报告