AcWing 889. 满足条件的01序列(卡特兰数应用)

满足条件的01序列

假设长度为n个序列要求满足题意1的前缀0的个数不能超过1的个数
将问题抽象为从(0, 0)到(n, n)
向上走一个代表这一步对应序列中的值是1,向右走代表序列中的值是0
图来自番茄酱
要想满足1的前缀0的数量大于1的数量就需要满足所有路过的途径在y = x这个函数个下面
但是如何表达呢?
我们采用所有到(n, n)的方案的集合减去越过y = x + 1这个直线的方案集合
因为越过y = x + 1 这个直线的方案集合可以表示为从(0, 0)到(n - 1, n + 1){(n, n)关于 y = x + 1对称的点}的方案集合
而这个答案 C ( n 2 n ) − C ( n − 1 2 n ) C\binom{n}{2n} - C\binom{n - 1}{2n} C(2nn)C(2nn1)
= 2 n ! n ! ∗ n ! − 2 n ! ( n + 1 ) ! ( n − 1 ) ! = \frac{2n!}{n!*n!} - \frac{2n!}{(n + 1)!(n - 1)!} =n!n!2n!(n+1)!(n1)!2n!

= 2 n ! ∗ ( n + 1 ) n ! ∗ ( n + 1 ) ! − 2 n ! ∗ n n ! ∗ ( n + 1 ) ! = \frac{2n!*(n + 1)}{n! * (n + 1)!} - \frac{2n! * n}{n! * (n + 1)!} =n!(n+1)!2n!(n+1)n!(n+1)!2n!n

= 1 ( n + 1 ) 2 n ! n ! ∗ n ! = \frac{1}{(n + 1)} \frac{2n!}{n!*n!} =(n+1)1n!n!2n!
称为卡特兰数

= C ( n 2 n ) n + 1 = \frac{C\binom{n}{2n}}{n + 1} =n+1C(2nn)
2n是x的跨度和y的跨度的和

AcWing 889. 满足条件的01序列

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
int n;

int qmi(int a, int b, int c)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = (LL) res * a % mod;
        a = (LL) a * a % mod;
        b >>= 1;
    }
    return res;
}

int main()
{
    scanf("%d", &n);
    int x = 1, y = 1;
    for (int i = 1; i <= 2 * n; i ++) x = (LL)x * i % mod;
    for (int i = 1; i <= n; i ++) y = (LL)y * i % mod;
    //要注意除(n + 1) 也要求逆元因为后面还要% mod
    printf("%lld", (LL) x * qmi(y, mod - 2, mod) % mod * qmi(y, mod - 2, mod) % mod * qmi(n + 1, mod - 2, mod) % mod);
    return 0;
}
  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ˇasushiro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值