AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 889. 满足条件的01序列    原题链接    简单

作者: 作者的头像   番茄酱 ,  2020-02-22 16:44:50 ,  所有人可见 ,  阅读 10904


127


70

题目描述:给定 $n$ 个 $0$ 和 $n$ 个 $1$,它们将按照某种顺序排成长度为 $2n$ 的序列,求它们能排列成的所有序列中,能够满足任意前缀序列中 $0$ 的个数都不少于 $1$ 的个数的序列有多少个。答案对 $10^9+7$ 取模。

数据范围:$1≤n≤10^5$

组合计数,卡特兰数

解法

将 $01$ 序列置于坐标系中,起点定于原点。若 $0$ 表示向右走,$1$ 表示向上走,那么任何前缀中 $0$ 的个数不少于 $1$ 的个数就转化为,路径上的任意一点,横坐标大于等于纵坐标。题目所求即为这样的合法路径数量。

下图中,表示从 $(0,0)$ 走到 $(n,n)$ 的路径,在绿线及以下表示合法,若触碰红线即不合法。

Catalan.png

由图可知,任何一条不合法的路径(如黑色路径),都对应一条从 $(0,0)$ 走到 $(n-1,n+1)$ 的一条路径(如灰色路径)。而任何一条 $(0,0)$ 走到 $(n-1,n+1)$ 的路径,也对应了一条从 $(0,0)$ 走到 $(n,n)$ 的不合法路径。

答案如图,即卡特兰数。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 200010, mod = 1e9 + 7;

int n;
int fact[N], infact[N];

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

void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++) {
        fact[i] = (LL)fact[i - 1] * i % mod;
        infact[i] = (LL)infact[i - 1] * ksm(i, mod - 2) % mod;
    }
}

int main() {
    init();
    cin >> n;
    int res = (LL)fact[2 * n] * infact[n] % mod * infact[n] % mod * ksm(n + 1, mod - 2) % mod;
    cout << res << endl;
    return 0;
}

44 评论


用户头像
世蒂   2022-09-29 19:29      8    踩      回复

好图!偷了(会标注来源的


用户头像
loverin   2021-07-29 13:39      3    踩      回复

为什么除(n+1)也要用逆元来算qaq

用户头像
Makisekurisu_4   2021-07-30 20:12         踩      回复

只要$\pmod p$ ,且$p$是质数,都必然是存在一个对应的逆元. 使得$a * a^{-1) \equiv 1 \pmod p$.

用户头像
loverin   2021-07-30 20:57    回复了 Makisekurisu_4 的评论      1    踩      回复

是只要mod了都要用逆元来算吗?直接除是不对的吗

用户头像
Makisekurisu_4   2021-07-30 21:44    回复了 loverin 的评论      9    踩      回复

根据我百度的模运算的运算法则,好像没有一个是除法,所以逆元的作用:保证计算过程中,每次计算符合模运算的规则.(模运算规则百度即可)

比如求$\frac{a}{b}\pmod p$,($p$是质数).

$\frac{a \bmod p}{b \bmod p}$ != 所求原式,因为没有除法的运算规则.但是如果我们找到一个$x$,使得

$a \times x \equiv \frac{a}{b} \pmod p$.

通过费马小定理可知,当模数$p$为质数,则

$a^{p-1} \equiv 1 \pmod p$

变换等式为 $a \times a^{p-2} \equiv 1 \pmod p$ 显然,$a^{p-2}$就是所求逆元.

用户头像
Makisekurisu_4   2021-07-30 21:45    回复了 loverin 的评论      5    踩      回复

也就是说逆元的作用其实就是等量替代除法运算,变成乘法.

用户头像
loverin   2021-07-30 21:59    回复了 Makisekurisu_4 的评论         踩      回复

谢谢dalao。数论太难了qaq

用户头像
Makisekurisu_4   2021-07-30 22:08    回复了 loverin 的评论         踩      回复

是啊= =我觉得学算法就是学完后写博客,记录学习笔记= = 很多代码我都是跟着模仿的.写笔记的时候才顺便自己再写一遍…

用户头像
柠檬味的猪已黑化   2022-06-09 15:18    回复了 Makisekurisu_4 的评论         踩      回复

太棒了吧这也

用户头像
Moyou   2022-06-09 22:47    回复了 loverin 的评论         踩      回复

直接用除法是对的,但是比起逆元所需要的乘法运算慢很多,为了追求效率所以求逆元

用户头像
diandian2020   2022-07-15 17:56    回复了 Moyou 的评论      2    踩      回复

不是吧,本来应该是能够整除的,但是为了避免写高精度,我们都是边算边模的。而在模意义下就不一定整除了,所以我们得找到一种能避免除法却又能满足整除性质的运算。

用户头像
Moyou   2022-07-18 01:32    回复了 diandian2020 的评论      3    踩      回复

有道理,我一个月前写的我自己都蒙了

用户头像
thebeatles   4个月前    回复了 diandian2020 的评论         踩      回复

直接用除法不行的,乘上1 / 3和乘 3在模p意义下的逆元不是一个概念。

用户头像
thebeatles   4个月前    回复了 diandian2020 的评论         踩      回复

直接用除法不行的,乘上1 / 3和乘 3在模p意义下的逆元不是一个概念。


用户头像
杨万里   1个月前      1    踩      回复

要是能严格证明就好了,光有个图,还是觉得有点那个了……


用户头像
clina   5个月前         踩      回复

orz


用户头像
糊涂   8个月前         踩      回复

为什么最后必须ksm(n+1,mod-2) 前面已经预处理了,infact[n+1]怎么不行那?

用户头像
Lastweek   2个月前         踩      回复

ksm(n+1,mod-2) 是(n+1)的逆元,infact[n+1]是(n+1)!的逆元


用户头像
xhQYm   9个月前         踩      回复

emm这预处理逆元没有意义,增加了复杂度,但是题解写得好

用户头像
早上起来胡辣汤就着算法题会不会更下饭点   5天前         踩      回复

是的,题目只有一组数据


用户头像
Keven11   2023-03-18 18:21         踩      回复

懂了!解释的很清楚啊!

用户头像
Keven11   2023-03-18 18:21         踩      回复

我指的那个卡特兰数


用户头像
Paraline   2023-02-21 14:07         踩      回复

好偷,图了!


用户头像
醒来   2021-11-28 14:23         踩      回复

这么预处理有点浪费时间吧, 直接求逆元就行了.

用户头像
diandian2020   2022-07-15 17:53         踩      回复

不是,是因为分母是阶乘,我们需要计算阶乘的逆元,你能一个一个乘


用户头像
jieHeEternity   2021-08-13 00:00         踩      回复

如何用欧几里得算法求逆元呢

用户头像
六七   2021-08-27 23:24         踩      回复

y总前面有视频


用户头像
alexyyywwwddd   2021-06-17 19:56         踩      回复

卧槽,这方法强的一


用户头像
阿轩   2021-05-17 02:03         踩      回复

大佬 为什么

LL mz=fact[b]%p*infact[a-b]%p*infact[b]%p;
LL nmz=fact[b-1]%p*infact[a-b+1]%p*infact[b-1]%p;
LL res=mz-nmz%p;

按原来的公式写会不对呢??

用户头像
白子伍   2022-05-08 10:57         踩      回复

你把mz和nmz,都加上mod ,再%mod,最后的res写成res=(mz-nmz+mod)%mod,应该就对了


用户头像
feifei   2021-04-07 21:29         踩      回复

为啥不合法的路径数是C(n - 1) 2n呢?

用户头像
番茄酱   2021-04-07 22:06      1    踩      回复

即从 (0, 0) 走到 (n - 1, n + 1) 的所有方案数,一共要走 2n 步,其中向右走 n-1 步,向上走 n+1 步,组合数就是 C(2n, n - 1) 或者 C(2n, n + 1)

用户头像
yrz_1   2022-03-19 06:38    回复了 番茄酱 的评论         踩      回复

👍🏻 C(2n, n-1) == C(2n, n+1)


用户头像
楚天   2020-10-01 11:31         踩      回复
int res = (LL)fact[2 * n] * infact[n] % mod * infact[n] % mod * ksm(n + 1, mod - 2) % mod;

大佬,这里的为什么要强制转化成long long 如果不转会怎么样

用户头像
番茄酱   2020-10-01 15:43         踩      回复

因为两个int相乘可能会爆int,所以先强制转化成long long了比较保险

用户头像
楚天   2020-10-01 16:00    回复了 番茄酱 的评论         踩      回复

那个我强制转化的是fact[2*n]还是这整个式子

用户头像
番茄酱   2020-10-01 16:04    回复了 楚天 的评论         踩      回复

只是fact[2 * n],这样他就是LL的,然后LL和后面的int相乘,int自动会转化为LL

用户头像
楚天   2020-10-01 16:25    回复了 番茄酱 的评论         踩      回复

好的,明白了


用户头像
番茄酱   2020-04-10 22:34         踩      回复

hh,ipad上的notability 配合 apple pencil 画的(其实就是只是画了几根直线而已呀)

用户头像
zc2077   2020-04-10 23:31         踩      回复

知道了!感谢哦

用户头像
再见_8   2020-04-16 16:04         踩      回复

主要字好看

用户头像
捡到一束光   2020-05-21 16:25         踩      回复

这字也太好看了吧


用户头像
zc2077   2020-04-10 21:35         踩      回复

请问你画图的工具是什么呀,很漂亮~

用户头像
杨大鑫_ωノ   2021-06-03 14:26      1    踩      回复

Notability


你确定删除吗?

© 2018-2024 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息