Description
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
Input
输入数据是一行,包括2个数字n和m
Output
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
Sample Input
2 2
Sample Output
2
HINT
【数据范围】
对于30%的数据,保证1<=m<=n<=1000
对于100%的数据,保证1<=m<=n<=1000000
题解(转载)
首先,我们设选$1$为$(1,1)$,选$0$为$(1,-1)$
目标就是$(n+m,n-m)$
总方案数为$C_{n+m}^n$,因为有$n+m$个位置,放$n$个$1$
然后要减去不合法的即线路通过$y=-1$的。将线路与$y=-1$交点的左边沿着$y=-1$做对称操作,则最后等价于从$(0,-2)$走到$(n+m,n-m)$的方案数
所以向上走$n-m+2$
则有$x-y=n-m+2$
$x+y=n+m$
$x=n+1,y=m-1$
所以不合法方案为$C_{n+m}^{n+1}$
$ans=C_{n+m}^n-C_{n+m}^{n+1}$
求这些用模逆元,$O(n)$求解
1 //It is made by Awson on 2017.10.9 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <cmath> 7 #include <stack> 8 #include <queue> 9 #include <vector> 10 #include <string> 11 #include <cstdio> 12 #include <cstdlib> 13 #include <cstring> 14 #include <iostream> 15 #include <algorithm> 16 #define LL long long 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 #define Max(a, b) ((a) > (b) ? (a) : (b)) 19 #define sqr(x) ((x)*(x)) 20 using namespace std; 21 const int N = 2000000; 22 const int MOD = 20100403; 23 24 int n, m; 25 int cnt[N+5]; 26 int A[N+5], B[N+5]; 27 28 void prepare() { 29 A[0] = B[0] = A[1] = B[1] =1; 30 for (int i = 2; i <= N; i++) 31 B[i] = -(LL)(MOD/i)*B[MOD%i]%MOD; 32 for (int i = 1; i <= N; i++) 33 A[i] = (LL)A[i-1]*i%MOD, 34 B[i] = (LL)B[i-1]*B[i]%MOD; 35 } 36 void work() { 37 scanf("%d%d", &n, &m); 38 prepare(); 39 printf("%lld ", ((LL)A[m+n]*B[m]%MOD*B[n]%MOD-(LL)A[m+n]*B[m-1]%MOD*B[n+1]%MOD+2*MOD)%MOD); 40 } 41 int main() { 42 work(); 43 return 0; 44 }