あなたの蛙が帰っています
题目链接
这道题是考卡特兰数的
题目描述
输入描述:
第一行一个数 T ,表示蛙蛙有 T 组询问。
接下去 T 行,每行一个正整数 N, 表示目的地的个数(入栈元素个数)。
1≤T≤200
1≤N≤10^5
输出描述
输出共 TT 行,每行一个答案,格式形如Case #1: 3 ,具体可见样例。
答案可能较大,请对 998244353 取模后输出。
输入样式
3
3
9
24
输出样式
Case #1: 3
Case #2: 3432
Case #3: 508887030
算法分析
这个题用到了卡特兰数,卡特兰数主要用于求组合数的方案数,规律是1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796,他可以求,矩阵连乘的方案数,栈的出栈序列,n个结点构成的二叉树有几种情况…
卡特兰数的常见问题
卡特兰数的求解
(1) h(n)= h(0)h(n-1)+h(1)h(n-2) + … + h(n-1)h(0) (n>=2)
(2) h(n)=h(n-1)(4n-2)/(n+1)
(3) h(n)=C(2n,n)/(n+1) (n=0,1,2,…)
(4) h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,…)
程序中用的是第二种,题目中的数很大要用到求余
1 (a + b) % p = (a % p + b % p) % p
2(a - b) % p = (a % p - b % p) % p
3(a * b) % p = (a % p * b % p) % p
4.a ^ b % p = ((a % p)^b) % p
这其中没有a/b%p;
a/b%p要用到逆元来求解逆元中的费马小定理推出来
(b/a)%m 可以变成 ba^(m-2)%m
当m较大时,要用到快速幂
所以这道题的最终就是h(n)=h(n-1)(4n-2)/(n+1)取余
kt[i]=kt[i-1](4i-2)%mod*ksm(i+1,mod-2)%mod;
题目还说第一个不能先出栈
所以答案要减去kt[i-1] (在第一个出去的情况下剩余的排列方式)
代码实现
#include<iostream>
#include<math.h>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define mod 998244353
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll kt[maxn]={0,1};
ll ksm(ll a,ll b)//快速幂为了求((4*n-2)/(n+1))%mod==>(4*n-2)%mod*ksm(n+1,mod-2)%mod;
{
ll ans=1;
while(b)
{
if(b%2)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void inti()//求卡特兰数组
{
for(int i=2;i<=100000;i++)
{
kt[i]=kt[i-1]*(4*i-2)%mod*ksm(i+1,mod-2)%mod;
}
}
int main()
{
inti();
int t;
cin>>t;
int x;
for(int i=1;i<=t;i++)
{
cin>>x;
printf("Case #%d: ",i);
if(x==1)
cout<<0<<endl;
else
cout<<(kt[x]-kt[x-1]+mod)%mod<<endl;
}
}

这篇文章讲解了如何利用卡特兰数解决关于蛙蛙归途的问题,涉及到组合数方案数的计算,特别是通过递推公式h(n) = h(n-1)(4n-2)/(n+1)求解,并强调了在特定条件(第一个不能先出栈)下的解答调整。通过实例展示了算法实现和输出格式。
571

被折叠的 条评论
为什么被折叠?



