【题解】LuoGu1641:[SCOI2010]生成字符串

原题传送门
初赛卡特兰题
想象在一个坐标系中
e 1 e1 e1表示加入一个“1”, e 1 = ( 1 , 1 ) e1=(1,1) e1=(1,1)
e 2 e2 e2表示加入一个“0”, e 2 = ( 1 , − 1 ) e2=(1,-1) e2=(1,1)
问题转化成从 ( 0 , 0 ) (0,0) (0,0)出发,到达 ( n + m , n − m ) (n+m,n-m) (n+m,nm)且不走到 x x x轴以下的方案数

若不考虑是否走到 x x x轴下面,方案数为 C n + m m C_{n+m}^{m} Cn+mm
若考虑走到过 x x x轴下面的方案数,可以转化成从 ( 0 , − 2 ) (0,-2) (0,2)出发,其中有 m − 1 m-1 m1个“0”,走到 ( n + m , n − m ) (n+m,n-m) (n+m,nm)的方案数,可以手画以下证明,为 C n + m m − 1 C_{n+m}^{m-1} Cn+mm1

减一下就好了

Code:

#include 
#define maxn 2000010
#define LL long long
using namespace std;
const LL qy = 20100403;
int n, m;
LL fac[maxn], inv[maxn];

LL ksm(LL n, LL k){
	LL s = 1;
	for (; k; k >>= 1, n = n * n % qy) if (k & 1) s = s * n % qy;
	return s;
}

LL C(int n, int m){ return fac[n] * inv[n - m] % qy * inv[m] % qy; }

int main(){
	scanf("%d%d", &n, &m);
	fac[0] = 1;
	for (int i = 1; i <= n + m; ++i) fac[i] = fac[i - 1] * i % qy;
	inv[n + m] = ksm(fac[n + m], qy - 2);
	for (int i = n + m; i; --i) inv[i - 1] = inv[i] * i % qy;
	printf("%lld\n", (C(n + m, m) - C(n + m, m - 1) + qy) % qy);
	return 0;
}

你可能感兴趣的:(题解,LuoGu,题解,LuoGu)