COGS2287 [HZOI 2015]疯狂的机器人
2017-08-22 22:01
281 查看
【题目描述】
现在在二维平面内原点上有一只机器人他每次操作可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格)
但是由于本蒟蒻施展的大魔法,机器人不能走到横坐标是负数或者纵坐标是负数的点上
否则他就会big bang
给定操作次数n,求有多少种不同的操作序列使得机器人在操作后会回到原点
输出答案模998244353后的结果
注意如果两个操作序列存在某一时刻操作不同,则我们认为这两个操作序列不同
【输入格式】
输入n,表示操作次数n<=100000
【输出格式】
按要求输出答案【样例输入】
3
【样例输出】
7
【提示】
样例解释:机器人有7种操作序列
1、不走 不走 不走
2、不走 向右 向左
3、向右 不走 向左
4、向右 向左 不走
5、不走 向上 向下
6、向上 不走 向下
7、向上 向下 不走
正解:组合数学+$NTT$。
学习卡特兰数以后做这题好像不难?
我们把操作分为$3$类,向右和向左为一类,向上和向下为一类,不动为一类。
那么如果只考虑前两类中的任何一类,那就是卡特兰数,因为这就是要求有$n/2$个$+1$,$-1$,且所有前缀和都$>=0$的序列方案数。很显然,只有偶数能取前两种情况。
那么我们扩展一下,如果有前两种操作,该怎么做?
$f
$表示$n$步路回到原点的方案数,那么$f
=\sum_{i=0}^{n}a[i]*a[n-i]*\binom{n}{i}$。
$a[i]$表示前两类操作走$i$步的方案数,$a[i]=c[i/2]$,当且仅当$i$为偶数,$c$为卡特兰数。
也就是说,从第一类操作中选$i$步,第二类操作中选$n-i$步,最后再组合起来,就是这个方案。
上式我们已经可以用$NTT$优化,做到$O(nlogn)$的复杂度。
考虑第$3$中操作,其实很简单了。我们只要枚举前两个操作总共有多少步,再和第$3$个操作组合一下就行。
也就是$Ans=\sum_{i=0}^{n}f[i]*\binom{n}{i}$。
#include <bits/stdc++.h> #define il inline #define RG register #define ll long long #define rhl (998244353) #define N (500010) using namespace std; int inv ,fac ,ifac ,a ,c ,rev ,n,m,lg,ans; il int qpow(RG int a,RG int b){ RG int ans=1; while (b){ if (b&1) ans=1LL*ans*a%rhl; a=1LL*a*a%rhl,b>>=1; } return ans; } il void pre(){ fac[0]=ifac[0]=fac[1]=ifac[1]=inv[1]=1; for (RG int i=2;i<=(n<<1);++i){ inv[i]=1LL*(rhl-rhl/i)*inv[rhl%i]%rhl; fac[i]=1LL*fac[i-1]*i%rhl; ifac[i]=1LL*ifac[i-1]*inv[i]%rhl; } return; } il void NTT(int *a,RG int n,RG int f){ for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]); for (RG int i=1;i<n;i<<=1){ RG int gn=qpow(3,(rhl-1)/(i<<1)),x,y; for (RG int j=0,g=1;j<n;j+=i<<1,g=1) for (RG int k=0;k<i;++k,g=1LL*g*gn%rhl){ x=a[j+k],y=1LL*g*a[j+k+i]%rhl; a[j+k]=x+y; if (a[j+k]>=rhl) a[j+k]-=rhl; a[j+k+i]=x-y; if (a[j+k+i]<0) a[j+k+i]+=rhl; } } if (f==1) return; reverse(a+1,a+n); RG int inv=qpow(n,rhl-2); for (RG int i=0;i<n;++i) a[i]=1LL*a[i]*inv%rhl; return; } int main(){ #ifndef ONLINE_JUDGE freopen("robot.in","r",stdin); freopen("robot.out","w",stdout); #endif cin>>n; pre(); for (RG int i=1;i<=n;++i) c[i]=1LL*fac[i<<1]*ifac[i]%rhl*ifac[i]%rhl*inv[i+1]%rhl; for (m=1;m<=(n<<1);m<<=1) ++lg; a[0]=1; for (RG int i=1;i<=n;++i) if (!(i&1)) a[i]=1LL*c[i>>1]*ifac[i]%rhl; for (RG int i=0;i<m;++i) rev[i]=rev[i>>1]>>1|((i&1)<<(lg-1)); NTT(a,m,1); for (RG int i=0;i<m;++i) a[i]=1LL*a[i]*a[i]%rhl; NTT(a,m,-1); for (RG int i=0;i<=n;++i) a[i]=1LL*a[i]*fac[i]%rhl; for (RG int i=0;i<=n;++i) ans=(ans+1LL*a[i]*fac %rhl*ifac[i]%rhl*ifac[n-i])%rhl; printf("%d\n",ans); return 0; }
相关文章推荐
- [COGS2287][HZOI 2015]疯狂的机器人(NTT+组合数学)
- [COGS2287][HZOI 2015]疯狂的机器人(NTT)
- NKOJ 4028(HZOI 2015)疯狂的机器人(NTT+卡特兰数)
- 【COGS】2287:[HZOI 2015]疯狂的机器人 FFT+卡特兰数+排列组合
- BZOJ 2287. [HZOI 2015]疯狂的机器人 [FFT 组合计数]
- cogs 2287. [HZOI 2015]疯狂的机器人 (NTT优化DP)
- [COGS 2287][HZOI 2015]疯狂的机器人
- [HZOI 2015]疯狂的机器人
- 疯狂的机器人-软件
- 疯狂2015之云南之行
- [COGS2189][HZOI 2015]帕秋莉的超级多项式-NTT-多项式求逆-多项式求ln-多项式开方-多项式求exp-多项式快速幂
- 杂项(最小表示法):HZOI 2015 Glass Beads
- 羽毛球 机器人 Robocon 2015 泰国预选赛(全国大学生机器人竞赛)
- cogs 2123. [HZOI 2015] Glass Beads
- Bitset([HZOI 2015]偏序++)
- 疯狂打CALL,机器人抢镜时尚大典
- [HZOI 2015]复仇的序幕曲
- COGS 2188. [HZOI 2015] Math 题解
- PVCBOT【1号】疯狂的小强--避障机器人
- [cogs2314][HZOI 2015] Persistable Editor - 可持久化平衡树