题目描述
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
输入
输入数据是一行,包括2个数字n和m
输出
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
样例输入
2 2
样例输出
2
题解
数论-Catalan数
如果n=m,那么这道题就是裸的Catalan数问题,答案为C(2n,n)-C(2n,n-1)。
当这道题的n!=m时,我们可以同样按照Catalan数的思想来做。
先求出没有限制条件的方案数,显然为C(n+m,m)。
然后再考虑不满足条件的方案数。
设选择一个n表示+1,选择一个m表示-1,那么如果不满足条件,则一定存在一个位置的前缀和等于-1。
将这个位置及其前面的数n、m互换,即所有数乘上-1,那么整个序列的和变为n-m+2。
并且这样的操作只需要在新序列存在某个位置前缀和为1时满足条件,而初始值是0,最终值为n-m,一定存在,这是显然的。
故这样的新序列选择不受条件约束,且存在m-1个“-1”,所以发案数为C(n+m,m-1)。
所以最终答案为C(n+m,m)-C(n+m,m-1)。
另外网上存在一种几何证法,我觉得也挺好的,这里附上网址:http://www.cnblogs.com/jianglangcaijin/p/3443689.html
#include <cstdio>
#define mod 20100403
typedef long long ll;
ll fac[2000010];
ll pow(ll x , int y)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
ll cal(int n , int m)
{
return fac[n] * pow(fac[m] , mod - 2) % mod * pow(fac[n - m] , mod - 2) % mod;
}
int main()
{
int n , m , i;
scanf("%d%d" , &n , &m);
fac[0] = 1;
for(i = 1 ; i <= n + m ; i ++ ) fac[i] = fac[i - 1] * i % mod;
printf("%lld\n" , (cal(n + m , m) - cal(n + m , m - 1) + mod) % mod);
return 0;
}