您的位置:首页 > 其它

hdu 1133

2015-04-01 13:08 176 查看
这道题有一个巧妙的解法:

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!。

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <iterator>
#include <cmath>
#include <deque>
#include <stack>
#include <cctype>
using namespace std;

const int N = 1100;
const int INF = 0xfffffff;

typedef long long ll;
typedef long double ld;

#define INFL 0x7fffffffffffffffLL
#define met(a, b) memset(a, b, sizeof(a))
#define rep(c, a, b) for (int c = a; c < b; c++)
#define nre(c, a, b) for (int c = a; c > b; c--)

//h(n) = ( (4*n-2) / (n+1) ) * h(n-1);
//(m+n)! * (m-n+1) /(m+1)

int a
;

int main ()
{
int m, n, k = 1;
while (cin >> m >> n, m + n)
{
cout << "Test #" << k++ << ":" << endl;
if (m < n) {cout << 0 << endl; continue;}
met (a, 0);
a[0] = 1;
rep (i, 1, m + n + 1)
{
int t = 0;
rep (j, 0, N)
{
int x = a[j] * i;
if (i == m + n) x *= (m - n + 1);
x += t; a[j] = x % 10, t = x / 10;
}
}
int t = 0;
nre (j, N-1, -1)
{
int x = a[j] + t * 10;
a[j] = x / (m + 1), t = x % (m + 1);
}

int len = N - 1;
while (a[len] == 0) len--;
while (len >= 0) cout << a[len--];
cout << endl;
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: