题目描述:
QAQ…
题目分析:
既然我们想要回到起点,那么就得让上下步数一样多,左右步数一样多,并且任何时刻上的步数比下的步数多,右的步数比左的步数多,然后你就会发现,这个模型不就是卡特兰数列的进出栈模型嘛…
设F(i) 表示 走 i 步回到起点且这 i 步里不包含不行走步数的方案数
定义 g(i) 表示只能上下走,不能左右和不走,回到起点的方案数
显然当 i为偶数是
g
(
i
)
=
C
a
t
a
l
a
n
(
i
2
)
g(i)=Catalan(\frac{i}{2})
g(i)=Catalan(2i)
当 i 为奇数是
g
(
i
)
=
0
g(i)=0
g(i)=0
显然 上下走 i 步 方案与 左右走 i 步的方案一致
那么
F
(
i
)
=
∑
j
=
0
i
g
(
i
)
∗
g
(
i
−
j
)
∗
C
(
i
,
j
)
F(i)=\sum_{j=0}^{i}g(i)*g(i-j)*C(i,j)
F(i)=∑j=0ig(i)∗g(i−j)∗C(i,j)
把组合数展开可得
F
(
i
)
=
i
!
∗
∑
j
=
0
i
g
(
j
)
j
∗
g
(
i
−
j
)
i
−
j
F(i)=i!*\sum_{j=0}^{i}\frac{g(j)}{j}*\frac{g(i-j)}{i-j}
F(i)=i!∗∑j=0ijg(j)∗i−jg(i−j) 后面的部分就是个卷积形式了,上NTT快速统计即可
最后的答案显然是
∑
i
=
0
n
f
(
i
)
∗
c
(
n
,
i
)
\sum_{i=0}^{n} f(i)*c(n,i)
∑i=0nf(i)∗c(n,i)
这里用的卡特兰数列计算公式是
C
a
t
a
l
a
n
(
i
)
=
C
(
2
n
,
n
)
−
C
(
2
n
,
n
−
1
)
Catalan(i)=C(2n,n)-C(2n,n-1)
Catalan(i)=C(2n,n)−C(2n,n−1)
题目链接:
Ac 代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define int long long
const int maxm=300005;
const int mod=998244353;
int Catalan[maxm],g[maxm],f[maxm],mul[maxm],rev[maxm],l;
inline int fastpow(int x,int y)
{
int ans=1;
for(;y;y>>=1,x=(x*x)%mod) if(y&1) ans=(ans*x)%mod;
return ans;
}
inline int C(int n,int m)
{
int x=mul[n],y=(mul[m]*mul[n-m])%mod;
int inv=fastpow(y,mod-2);
return (x*inv)%mod;
}
inline void NTT(int *a,int n,int f)
{
for(int i=0;i<n;i++) rev[i]=((rev[i>>1]>>1)|((i&1)<<(l-1)));
for(int i=0;i<n;i++) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
for(int i=1;i<n;i<<=1)
{
int wn=fastpow(3,~f?(mod-1)/(i<<1):(mod-1)-(mod-1)/(i<<1));
for(int j=0;j<n;j+=(i<<1))
{
int w=1;
for(int k=0;k<i;k++,w=(w*wn)%mod)
{
int x=a[j+k],y=(a[i+j+k]*w)%mod;
a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
}
}
}
if(f==-1)
{
int inv=fastpow(n,mod-2);
for(int i=0;i<n;i++) a[i]=(a[i]*inv)%mod;
}
}
int n;
signed main()
{
//freopen("crazy_robot.in","r",stdin);
//freopen("crazy_robot.out","w",stdout);
mul[0]=1;
for(int i=1;i<maxm;i++) mul[i]=(mul[i-1]*i)%mod;
scanf("%lld",&n);
int m;
for(m=1;m<=2*n;m<<=1) l++;
for(int i=2;i<=n;i+=2) Catalan[i]=(C(i,i/2)-C(i,i/2-1)+mod)%mod;
for(int i=0;i<=n;i++) g[i]=(Catalan[i]*fastpow(mul[i],mod-2))%mod;
g[0]=1;
NTT(g,m,1);
for(int i=0;i<m;i++) f[i]=((g[i]*g[i])%mod)%mod;
NTT(f,m,-1);
for(int i=0;i<=n;i++) f[i]=(f[i]*mul[i])%mod;
int ans=0;
for(int i=0;i<=n;i++) ans=(ans+(f[i]*C(n,i))%mod)%mod;
printf("%lld\n",ans);
return 0;
}