超级卡特兰数(又称大施罗德数)

题目链接:https://www.nowcoder.com/acm/contest/146/B

把前四项丢进OEIS,就能知道是

施罗德数

参照百科:https://baike.baidu.com/item/%E6%96%BD%E7%BD%97%E5%BE%B7%E6%95%B0/16536292

施罗德数一组可用于解决组合数学中某些问题的序列

施罗德数的前几项为1, 2, 6, 22, 90, 394, 1806, 8558, 41586, 206098,... (OEIS A006318)

但是按照施罗德数

{\color{Red} F_{n}=F_{n-1}+\sum_{k=0}^{n-1}F_{k}*F_{n-1-k}}

递推公式暴力肯定会超时,在网上搜索“施罗德数”可以查到“超级卡特兰数”,其递推公式为:

{\color{Red} F_{n}*(n+1)=(6*n-3)*F_{n-1}-(n-2)*F_{n-2}}

数列前几项为1, 1, 3, 11, 45, 197, 903, 4279, 20793, 103049, 518859, 2646723, 13648869, 71039373, 372693519, 1968801519, 10463578353, 55909013009, 300159426963, 1618362158587, 8759309660445, 47574827600981, 259215937709463……(从第0项开始的)

仔细观察可以看到这个数列和施罗德数除了f(1)以外都是2倍的关系,所以可以使用这个公式计算。

 

代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=3e5;
typedef long long LL;
#define mod 998244353

LL num[maxn];

LL inverse(LL x,LL y)///快速幂加费马小定理求逆元
{
    LL sum=1;

    while(y)
    {

        if(y&1) sum=sum*x%mod;

        y/=2;
        x=x*x%mod;

    }
    return sum%mod;
}


int main()
{
        int n;

        while(~scanf("%d",&n))
        {
            num[1]=num[0]=1;
            if(n==1) {
                printf("1\n");continue;
            }

            for(int i=2;i<=n;i++)
            {
                num[i]=((6*i-3)*num[i-1]%mod-(i-2)*num[i-2]%mod+mod)%mod*inverse(i+1,mod-2)%mod;
            }

            printf("%lld\n",num[n-1]*2%mod);
        }
        return 0;
}

 

我的标签:做个有情怀的程序员。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值