C.挖坑 | |||||
| |||||
Description | |||||
Quasrain 和 FZ 是好朋友。Quasrain 善于挖坑而 FZ 善于填坑。 这个游戏一共会持续 2N 天。在每一天都会有人挖坑或者填坑,并在本子上记录下“A”表示这天挖了坑,“B”表示填了坑。填坑必须填一个现存的还没有被填过的坑。 作为素质优秀的熊孩子,他们保证在最后一天结束的时候一定会恰好填平所有坑。 问本子上可能有多少种不同的 AB 序列 | |||||
Input | |||||
第一行一个数 T 表示数据组数(T<=100000) 之后 T 行每行一个数 N,意义如题面所示(1<=N<=1000)
| |||||
Output | |||||
对于每组数据输出方案数,对 998244353 取模 | |||||
Sample Input | |||||
3 1 2 3 | |||||
Sample Output | |||||
1 2 5 | |||||
Hint | |||||
对于第三组样例: 可能的 AB 序列分别为:{AAABBB},{AABABB},{AABBAB},{ABAABB},{ABABAB} |
第一次接触卡特兰数,一定要记住公式!!
题解:
相当于求卡特兰数的第x项
①:F[n]=C(2n,n)-C(2n,n-1)
②:或者F[n]=F[n-1]*(4*n-2)/(n+1)
在模意义下除法要使用乘法逆元
第一种:
由于数据不大,可以用组合数来求解
F[n]=C(2n,n)-C(2n,n-1)
组合数的求解用到杨辉三角的知识,即C(n,m)=C(n-1,m-1)+C(n-1,m)
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
typedef long long ll;
const int xmax=1e5+7;
const int INF=1e9+7;
const int mod=998244353;
using namespace std;
ll c[2220][2220];
int n;
void init()
{
memset(c,0,sizeof(c));
c[1][0]=1;c[1][1]=1;
for(int i=2;i<=2020;i++){
for(int j=0;j<=i;j++){
if(j==0) c[i][j]=1;
else c[i][j]=(c[i-1][j]+c[i-1][j-1]);
}
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ll ans=(c[2*n][n]-c[2*n][n-1])%mod;
printf("%lld\n",ans);
}
return 0;
}
第二种:
利用第二个公式,这里因为除数取模,需要用到乘法逆元的知识
什么是逆元?
对于一个除法来说
a/b = a*(b的逆元)
所以对于a/b %mod = a* (b的逆元) %mod
求解逆元有三种方法:
方法一:拓展欧几里得求逆元
设a mod p的逆元为x
则 ax=1 (mod p) 拓展欧几里得求解即可
方法二 费马小定理求解
a^oula(p) = 1 (mod p)
// oula(p)是关于欧拉函数求小于p的正整数中与p互质的个数
点击https://blog.csdn.net/weixin_43916296/article/details/86589159了解
方法三 线性推逆元
A[i] = -(p / i) * A[p % i];
因为998244353为质数,所以可以用费马小定理和快速幂来求解
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
typedef long long ll;
const ll mod=998244353;
using namespace std;
ll f[200200];
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b%2)
ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans%mod;
}
void init()
{
f[1]=1;f[2]=2;
for(int i=3;i<=1010;i++)
{
f[i]=((f[i-1]*(4*i-2))%mod*qpow(i+1,mod-2))%mod;
}
}
int main()
{
init();
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%lld\n",f[n]);
}
return 0;
}