【acwing】889. 满足条件的01序列**(卡特兰数)

穿越隧道
【acwing】889. 满足条件的01序列**(卡特兰数)_第1张图片

通过将01序列转为二维坐标轴上的路径:
将0表示为向右走;将1表示为向上走
合法路径为y=x(含)和x轴之间的路径。
非法路径为y=x+1(只要路径和y=x+1)相交时,就是非法路径。合法路径(6,6)以(y=x+1)为轴进行对称时,为(5,7) C 12 5 或 C 12 7 C_{12}^5 或C_{12}^7 C125C127
即合法路径等于 C 2 n n ( 总 路 径 ) − C 2 n n − 1 ( 非 法 路 径 ) = C 2 n n n + 1 C_{2n} ^ n(总路径) - C_{2n}^{n-1}(非法路径) = \frac{C_{2n}^n}{n+1} C2nnC2nn1(=n+1C2nn
C a b = C 2 n n = ( 2 n ) ! n ! ∗ n !   =   2 n ∗ ( 2 n − 1 ) ∗ . . . ∗ ( 2 n − n + 1 ) 1 ∗ 2 ∗ . . . ∗ n C_a^b = C_{2n}^n = \frac{(2n)!}{n!*n!} \ = \ \frac{2n * (2n-1) * ... * (2n - n + 1)}{1*2*...*n} Cab=C2nn=n!n!(2n)! = 12...n2n(2n1)...(2nn+1)
所以,需要求1~b和n+1的逆元。

#include 
#include 
#include 
/*因p是质数,所以可以用费马定理。
费马定理可以用快速幂求解。
如果p不是质数,则只能用扩展欧几里得*/
const int mod = 1e9 + 7;
using namespace std;
typedef long long ll;
ll qmi(int a, int b){
	ll res = 1 % mod;
	while(b){
		if(b & 1) res = (1ll) * res * a % mod;
		a = (1ll) * a * a % mod;
		b >>= 1; 
	}
	return res;
}
int main(){
	int n;
	scanf("%d",&n);
	int a = 2 * n, b = n;
	ll res = 1;
	for(int i = a; i > a - b; i--) res = (1ll) * res * i % mod;
	for(int i = 1; i <= b; i++) res = (1ll) * res * qmi(i,mod - 2) % mod;
//	for(int i = 1; i <= b; i++) res = (1ll) * res * qmi(i, mod - 2, mod) % mod;
	res = (1ll) * res * qmi(n + 1, mod - 2) % mod;
	printf("%lld\n",res);
	return 0;
} 

你可能感兴趣的:(acwing,数学知识,c++)