White and Black Balls 题解
我终于会 c a t a l a n catalan catalan 了hh。
题意:有 n n n 个白球, m m m 个蓝球,将这些球排成一排,记 w i w_i wi 表示 [ 1 , i ] [1, i] [1,i] 的白球的个数, b i b_i bi 表示 [ 1 , i ] [1, i] [1,i] 的蓝球的个数,要求 ∀ w i < b i + k \forall w_i < b_i + k ∀wi<bi+k。
我们考虑 m < n + k m < n + k m<n+k 的情况
将 W W W 操作当做 ( x , y ) → ( x + 1 , y ) (x, y) \rightarrow (x + 1, y) (x,y)→(x+1,y),将 B B B 操作当做 ( x , y ) → ( x , y + 1 ) (x, y) \rightarrow (x, y + 1) (x,y)→(x,y+1),那么终点是 ( n , m ) (n, m) (n,m)。
举个例子,序列为 WBBWBBWW, k = 0 k = 0 k=0
怎么判断方案合不合法呢?如果发现路径和
y
=
x
+
k
+
1
y = x + k + 1
y=x+k+1 相交,则不合法,否则合法。考虑容斥,方案总数是
C
n
+
m
n
C_{n + m}^{n}
Cn+mn,那么现在只考虑不合法的情况。
把这个路径在 y = x + k + 1 y = x + k + 1 y=x+k+1 以下的部分(除与 y = x + k + 1 y = x + k + 1 y=x+k+1 相交的最后一个点到 ( n , m ) (n, m) (n,m) 的路径)以 y = x + k + 1 y = x + k + 1 y=x+k+1 为对称轴翻折过去。如图所示。
这时候原点翻折到了 ( − k − 1 , k + 1 ) (-k - 1,k + 1) (−k−1,k+1),所有 ( − k − 1 , k + 1 ) → ( n , m ) (-k - 1, k + 1) \rightarrow (n, m) (−k−1,k+1)→(n,m) 的路径都必定与 y = x + k + 1 y = x + k + 1 y=x+k+1 相交,所以把在 y = x + k + 1 y = x + k + 1 y=x+k+1 上方的部分翻折回去就是一种不合法的情况。
所以不合法的情况是: C ( n + k + 1 ) + ( m − k − 1 ) m − k − 1 = C n + m m − k − 1 C_{(n + k + 1) + (m - k - 1)}^{m - k - 1} = C_{n + m}^{m - k - 1} C(n+k+1)+(m−k−1)m−k−1=Cn+mm−k−1
那么最终答案就是: C n + m n − C n + m m − k − 1 C_{n + m}^{n} - C_{n + m}^{m - k - 1} Cn+mn−Cn+mm−k−1。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int Maxn = 2 * 1e6;
const LL Mod = 1e9 + 7;
int n, m, k;
LL fac[Maxn + 5], inv_fac[Maxn + 5];
LL quick_pow (LL x, LL y) {
LL res = 1;
while (y) {
if (y & 1) res = (res * x) % Mod;
x = (x * x) % Mod; y >>= 1;
}
return res;
}
LL inv (LL x) {
return quick_pow (x, Mod - 2);
}
LL C (LL x, LL y) {
if (y == 0 || x == y) return 1;
return fac[x] * inv_fac[y] % Mod * inv_fac[x - y] % Mod;
}
int main () {
fac[1] = 1; for (int i = 2; i <= Maxn; i++) fac[i] = fac[i - 1] * i % Mod;
inv_fac[Maxn] = inv (fac[Maxn]); for (int i = Maxn - 1; i >= 1; i--) inv_fac[i] = inv_fac[i + 1] * (i + 1) % Mod;
cin >> m >> n >> k;
if (n + k + 1 <= m) {
printf ("0");
return 0;
}
printf ("%lld", (C (n + m, n) - C (n + m, m - k - 1) + Mod) % Mod);
return 0;
}