【题目描述】
现在在二维平面内原点上有一只机器人
他每次操作可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格)
但是由于本蒟蒻施展的大魔法,机器人不能走到横坐标是负数或者纵坐标是负数的点上
否则他就会big bang
给定操作次数n,求有多少种不同的操作序列使得机器人在操作后会回到原点
输出答案模998244353后的结果
注意如果两个操作序列存在某一时刻操作不同,则我们认为这两个操作序列不同
【输入格式】
输入n,表示操作次数
n<=100000
【输出格式】
按要求输出答案
【样例输入】
3
【样例输出】
7
【提示】
样例解释:
机器人有7种操作序列
1、不走 不走 不走
2、不走 向右 向左
3、向右 不走 向左
4、向右 向左 不走
5、不走 向上 向下
6、向上 不走 向下
7、向上 向下 不走
将操作分3类:向上下,向左右,不动
$f[i]$表示只考虑前两类走i步到原点的方案数
$$f[n]=sum_{i=0}^{n}a[i]*a[n-i]*inom{n}{i}$$
$a[i]$表示向上向下(或向左向右)走i步回到原点的方案数
显然i为偶数时才有方案否则$a[i]$为0
然后不动就直接枚举f
$$ans=sum_{i=0}^{n}f[i]*inom{n}{i}$$
$a[i]$显然就是卡特兰数第$i/2$项
因为任意时刻向上的前缀和总是大于向下的
至于卷积就直接把组合数拆开,把分母分到a上,即:
$$a[i]=C[i/2]*i!^{-1}$$
NTT求出f后再乘上$n!$
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef int lol; 8 const int N=100000; 9 int Mod=998244353; 10 int G=3; 11 int a[8*N],fac[5*N],R[8*N],ifac[5*N],inv[5*N],c[5*N],f[8*N],ans; 12 int qpow(int x,int y) 13 { 14 int res=1; 15 while (y) 16 { 17 if (y&1) res=1ll*res*x%Mod; 18 x=1ll*x*x%Mod; 19 y>>=1; 20 } 21 return res; 22 } 23 void NTT(int *A,int len,int o) 24 {int wn,w,i,j,k,x,y; 25 for (i=0;i<len;i++) 26 if (i<R[i]) swap(A[i],A[R[i]]); 27 for (i=1;i<len;i<<=1) 28 { 29 wn=qpow(G,(Mod-1)/(i<<1)); 30 if (o==-1) wn=qpow(wn,Mod-2); 31 for (j=0;j<len;j+=(i<<1)) 32 { 33 w=1; 34 for (k=0;k<i;k++,w=1ll*w*wn%Mod) 35 { 36 x=A[j+k];y=1ll*w*A[j+k+i]%Mod; 37 A[j+k]=x+y; 38 if (A[j+k]>=Mod) A[j+k]-=Mod; 39 A[j+k+i]=x-y; 40 if (A[j+k+i]<0) A[j+k+i]+=Mod; 41 } 42 } 43 } 44 if (o==-1) 45 { 46 int tmp=qpow(len,Mod-2); 47 for (i=0;i<len;i++) 48 A[i]=1ll*A[i]*tmp%Mod; 49 } 50 } 51 int main() 52 { 53 int i,len,lg,n; 54 scanf("%d",&n); 55 memset(a,0,sizeof(a)); 56 fac[0]=fac[1]=ifac[0]=ifac[1]=inv[1]=1; 57 for (i=2;i<=n*2;i++) 58 { 59 inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod; 60 fac[i]=1ll*fac[i-1]*i%Mod; 61 ifac[i]=1ll*ifac[i-1]*inv[i]%Mod; 62 } 63 for (i=1;i<=n;i++) 64 c[i]=1ll*fac[i<<1]*ifac[i]%Mod*ifac[i]%Mod*inv[i+1]%Mod; 65 a[0]=1; 66 for (i=2;i<=n;i++) 67 if ((i&1)==0) 68 a[i]=1ll*c[i>>1]*ifac[i]%Mod; 69 len=1; 70 while (len<=2*n) len*=2,lg++; 71 for (i=0;i<len;i++) 72 R[i]=(R[i>>1]>>1)|((i&1)<<(lg-1)); 73 NTT(a,len,1); 74 for (i=0;i<len;i++) 75 a[i]=1ll*a[i]*a[i]%Mod; 76 NTT(a,len,-1); 77 for (i=0;i<=n;i++) 78 f[i]=1ll*a[i]*fac[i]%Mod; 79 for (i=0;i<=n;i++) 80 ans=1ll*(ans+1ll*f[i]*fac[n]%Mod*ifac[i]%Mod*ifac[n-i]%Mod)%Mod; 81 printf("%d ",ans); 82 return 0; 83 }