这道题有一个巧妙的解法:
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 }