AcWing 889 满足条件的01序列

题目描述:

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

输出格式

共一行,包含整数n。

输出格式

共一行,包含一个整数,表示答案。

数据范围

1≤n≤10^5

输入样例:

3

输出样例:

5

分析:

将题目的1看作进栈,0看作出栈,任何时候出栈次数不能大于进栈次数,则本题可看做求栈混洗合法序列的数目。或者将1看作左括号,0看作右括号,就等价于括号匹配的合法数目了,故本题等价于求Catalan(n) = C(2n,n) / (n+1)。除法运算由于模数10^9 + 7是素数,故可以使用快速幂求乘法逆元来变成乘法运算。

卡特兰数公式的推导:可看作从坐标系中原点前进到(n,n)点的走法,1表示向右移动一格,0表示向上移动一格。如果没有限制的话相当于在2n步中选n步向右,一共C(2n,n)种走法,但是1的个数要始终大于0的个数说明走的轨迹要始终不能超过y = x这条直线,准确地说是不能触碰到y = x + 1这条线。一旦触碰到了,设第一次在x点触碰到了y = x + 1,则之后的轨迹的终点也是(n,n),将x到终点的路径关于y = x + 1做轴对称,得到另一条路径,终点是(n - 1,n + 1)。故任意一条触碰到y = x + 1的非法路径都可以转化为终点为(n - 1,n + 1)的路径,一共是C(2n,n - 1)种非法路径,故合法路径一共是C(2n,n) - C(2n,n - 1)。C(2n,n - 1) = (2n)! / ((n-1)! * (n + 1)!) = n / (n + 1) * (2n)! / (n! * n!) = n / (n + 1) * C(2n,n),故Catalan(n ) = C(2n,n) / (n + 1)。

#include <iostream>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int qmi(int a,int k,int p){
    int res = 1;
    while(k){
        if(k & 1)   res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    int res = 1;
    for(int i = 2 * n,j = 1;j <= n;i--,j++){
        res = (ll) res * i % mod;
        res = (ll) res * qmi(j,mod - 2,mod) % mod;
    }
    res = (ll)res * qmi(n + 1,mod - 2,mod) % mod;
    cout<<res<<endl;
    return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值