这道题有一个巧妙的解法:

n=0时,答案显然是m!

m<n时,答案是0

现在讨论m>=n的情况。

m=6,n=6时,一个非法的序列例如,001101100011(6个0,6个1),把第一个使序列非法的1右面的每个位翻转,即变成001101111100(5个0,7个1),可以看出每个非法的序列(6个0,6个1)都对应一个5个0,7个1的序列。

可以证明m个0,n个1的任意一个非法序列的翻转结果都是n-1个0,m+1个1的序列,而且前者跟后者是一一对应关系。因此,当我们知道n-1个0,m+1个1的序列的排列总数也就知道我们想求的序列的非法数。

 

所以这种情况下的最终答案是(C(m+n,m) - C(m+n,m+1))*m!*n!。

 

排列组合公式/排列组合计算公式

 

根据公式化简之后就是  (m+n)! * (m-n+1) /(m+1)

实际上是卡特兰数的一种变形。

 

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <string>
 8 #include <iterator>
 9 #include <cmath>
10 #include <deque>
11 #include <stack>
12 #include <cctype>
13 using namespace std;
14 
15 const int N = 1100;
16 const int INF = 0xfffffff;
17 
18 typedef long long ll;
19 typedef long double ld;
20 
21 #define INFL 0x7fffffffffffffffLL
22 #define met(a, b) memset(a, b, sizeof(a))
23 #define rep(c, a, b) for (int c = a; c < b; c++)
24 #define nre(c, a, b) for (int c = a; c > b; c--)
25 
26 //h(n) = ( (4*n-2) / (n+1) ) * h(n-1);
27 //(m+n)! * (m-n+1) /(m+1)
28 
29 int a[N];
30 
31 int main ()
32 {
33     int m, n, k = 1;
34     while (cin >> m >> n, m + n)
35     {
36         cout << "Test #" << k++ << ":" << endl;
37         if (m < n) {cout << 0 << endl; continue;}
38         met (a, 0);
39         a[0] = 1;
40         rep (i, 1, m + n + 1)
41         {
42             int t = 0;
43             rep (j, 0, N)
44             {
45                 int x = a[j] * i;
46                 if (i == m + n) x *= (m - n + 1);
47                 x += t; a[j] = x % 10, t = x / 10;
48             }
49         }
50         int t = 0;
51         nre (j, N-1, -1)
52         {
53             int x = a[j] + t * 10;
54             a[j] = x / (m + 1), t = x % (m + 1);
55         }
56 
57         int len = N - 1;
58         while (a[len] == 0) len--;
59         while (len >= 0) cout << a[len--];
60         cout << endl;
61     }
62     return 0;
63 }
View Code

 

posted on 2015-04-01 13:08  白夜叉降临  阅读(270)  评论(0编辑  收藏  举报