COGS 2287. [HZOI 2015]疯狂的机器人

首先可以知道的是,上下和左右是等价的,所以可以分开来算。

现在只考虑左右,而且不考虑不走的情况。

那么假设向右走是进栈,那么向左就是出栈,而且向右是是重要大于向左的。所以问题就等于了卡特兰数的进栈和出栈的方案数,即g[n]=C(2*n,n)-C(2*n,n-1)

现在来考虑不走的情况。

枚举有几步不走

Ans=for (int i=0; i<=n; i++) C(n,i)*for (int j=0; j<=i; j++) g[j]*g[i-j];

发现后面是卷积,于是用NTT优化一下。

(本蒟蒻不会用那些神奇的东西写式子,而且发现写∑好丑,就写for循环了2333)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <iostream>
 6 #define LL long long
 7 #define pi acos(-1)
 8 using namespace std;
 9 
10 const int mod=998244353;
11 const int maxn=200005;
12 
13 LL G=3,inv_G,inv_N;
14 
15 int ksm(int x, int p)
16 {
17     int sum=1;
18     for (;p;p>>=1,x=(LL)x*x%mod)
19         if (p&1) sum=(LL)sum*x%mod;
20     return sum;
21 }
22 
23 LL fac[maxn<<1],inv[maxn<<1],g[maxn<<2];
24 int n,N,rev[maxn<<2];
25 
26 LL C(int n, int m)
27 {
28     return fac[n]*inv[m]%mod*inv[n-m]%mod;
29 }
30 void pre()
31 {
32     inv_G=ksm(G,mod-2);
33     fac[0]=inv[0]=inv[1]=g[0]=1;
34     for (int i=1; i<2*maxn; i++) fac[i]=fac[i-1]*i%mod; 
35     for (int i=2; i<2*maxn; i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
36     for (int i=2; i<=n; i++) inv[i]=inv[i-1]*inv[i]%mod;
37     for (int i=2; i<=n; i+=2) g[i]=(C(i,i/2)-C(i,i/2-1)+mod)%mod*inv[i]%mod;
38 }
39 
40 void NTT(LL *a, int f)
41 {
42     for (int i=0; i<N; i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
43     for (int h=2; h<=N; h<<=1)
44     {
45         LL wn=ksm(f==1?G:inv_G,(mod-1)/h);//cout<<wn; system("pause");
46         for (int i=0; i<N; i+=h)
47         {
48             LL w=1;
49             for (int j=0; j<(h>>1); j++,w=w*wn%mod)
50             {
51                 LL x=a[i+j],y=a[i+j+(h>>1)]*w%mod;
52                 a[i+j]=(x+y)%mod;
53                 a[i+j+(h>>1)]=(x-y+mod)%mod;
54             }
55         }
56     }
57     if (f==-1) for (int i=0; i<N; i++) a[i]=a[i]*inv_N%mod*fac[i]%mod;
58 }
59 
60 int main()
61 {
62     freopen("crazy_robot.in","r",stdin); freopen("crazy_robot.out","w",stdout);
63     cin>>n;  pre();  int L=0;
64     for (N=1; N<n<<1; N<<=1) L++; inv_N=ksm(N,mod-2);// cout<<inv_N%mod;
65     for (int i=0; i<N; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
66     NTT(g,1); 
67     for (int i=0; i<=N; i++) g[i]=g[i]%mod*g[i]%mod; 
68     NTT(g,-1); LL ans=0;
69 //    for (int i=0; i<=N; i++) printf("%d\n",(LL)g[i]);
70     for (int i=0; i<=n; i++) ans=(ans+C(n,i)*g[i]%mod+mod)%mod;
71     cout<<ans<<endl;
72     return 0;
73 }

 

posted @ 2017-04-19 14:18  ws_ccd  阅读(180)  评论(0编辑  收藏  举报