COGS2287 [HZOI 2015]疯狂的机器人

【题目描述】

现在在二维平面内原点上有一只机器人

他每次操作可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格)

但是由于本蒟蒻施展的大魔法,机器人不能走到横坐标是负数或者纵坐标是负数的点上

否则他就会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]$表示$n$步路回到原点的方案数,那么$f[n]=\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}$。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define rhl (998244353)
 6 #define N (500010)
 7
 8 using namespace std;
 9
10 int inv[N],fac[N],ifac[N],a[N],c[N],rev[N],n,m,lg,ans;
11
12 il int qpow(RG int a,RG int b){
13   RG int ans=1;
14   while (b){
15     if (b&1) ans=1LL*ans*a%rhl;
16     a=1LL*a*a%rhl,b>>=1;
17   }
18   return ans;
19 }
20
21 il void pre(){
22   fac[0]=ifac[0]=fac[1]=ifac[1]=inv[1]=1;
23   for (RG int i=2;i<=(n<<1);++i){
24     inv[i]=1LL*(rhl-rhl/i)*inv[rhl%i]%rhl;
25     fac[i]=1LL*fac[i-1]*i%rhl;
26     ifac[i]=1LL*ifac[i-1]*inv[i]%rhl;
27   }
28   return;
29 }
30
31 il void NTT(int *a,RG int n,RG int f){
32   for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]);
33   for (RG int i=1;i<n;i<<=1){
34     RG int gn=qpow(3,(rhl-1)/(i<<1)),x,y;
35     for (RG int j=0,g=1;j<n;j+=i<<1,g=1)
36       for (RG int k=0;k<i;++k,g=1LL*g*gn%rhl){
37     x=a[j+k],y=1LL*g*a[j+k+i]%rhl;
38     a[j+k]=x+y; if (a[j+k]>=rhl) a[j+k]-=rhl;
39     a[j+k+i]=x-y; if (a[j+k+i]<0) a[j+k+i]+=rhl;
40       }
41   }
42   if (f==1) return; reverse(a+1,a+n); RG int inv=qpow(n,rhl-2);
43   for (RG int i=0;i<n;++i) a[i]=1LL*a[i]*inv%rhl;
44   return;
45 }
46
47 int main(){
48 #ifndef ONLINE_JUDGE
49   freopen("robot.in","r",stdin);
50   freopen("robot.out","w",stdout);
51 #endif
52   cin>>n; pre();
53   for (RG int i=1;i<=n;++i)
54     c[i]=1LL*fac[i<<1]*ifac[i]%rhl*ifac[i]%rhl*inv[i+1]%rhl;
55   for (m=1;m<=(n<<1);m<<=1) ++lg; a[0]=1;
56   for (RG int i=1;i<=n;++i) if (!(i&1)) a[i]=1LL*c[i>>1]*ifac[i]%rhl;
57   for (RG int i=0;i<m;++i) rev[i]=rev[i>>1]>>1|((i&1)<<(lg-1));
58   NTT(a,m,1); for (RG int i=0;i<m;++i) a[i]=1LL*a[i]*a[i]%rhl;
59   NTT(a,m,-1); for (RG int i=0;i<=n;++i) a[i]=1LL*a[i]*fac[i]%rhl;
60   for (RG int i=0;i<=n;++i)
61     ans=(ans+1LL*a[i]*fac[n]%rhl*ifac[i]%rhl*ifac[n-i])%rhl;
62   printf("%d\n",ans); return 0;
63 }
时间: 2024-10-12 20:40:48

COGS2287 [HZOI 2015]疯狂的机器人的相关文章

[HZOI 2015]疯狂的颜色序列

%ad大神的脑洞,这题是强制在线版的HH的项链 所以可以考虑树套树,和主席树之类的做法 对于每个点,可以将这个点的颜色上一次出现的位置插入到主席树里,对于每一个 l ~ r 的询问, l 到 r 之间有多少颜色上一次出现的位置在0 到 l-1 内就是答案 1 #define MAXN 500010UL 2 #include <cstdio> 3 #include <algorithm> 4 5 using namespace std; 6 7 int n, m, Rt[MAXN],

cogs 2320. [HZOI 2015]聪聪的世界题解

2320. [HZOI 2015]聪聪的世界 时间限制:6 s   内存限制:512 MB [题目描述] 背景: 聪聪的性取向有问题. 题目描述: 聪聪遇到了一个难题: 给出一个序列a1-an,完成以下操作: 1  x 询问从x向左数第一个<ax的数: 2  x 询问从x向左数第一个>ax的数: 3  x 询问从x向右数第一个<ax的数: 4  x 询问从x向右数第一个>ax的数: 5  x y 交换ax与ay: 6  x y w 给ax-ay加上w: 7  x y w 给ax-a

杂项(最小表示法):HZOI 2015 Glass Beads

[题目描述] 给定长度为n(n<=300000)的循环同构的字符串,定义最小表示为该字符串的字典序最小的同构表示,请输出这个表示. [输入格式] 第一行是串的长度,第二行是字符串. [输出格式] 串的最小表示. [样例输入] 10 helloworld [样例输出] dhelloworl [题目来源] HZOI2015 改编自poj1509 算法很显然,需要注意的是:s[len+1]要赋值成一个较大值. 1 #include <iostream> 2 #include <cstri

COGS 2188. [HZOI 2015] Math 题解

  题目描述: 给定n个数X1-Xn,求下面式子的值(整数部分): n<=107,xi<=109且互不相同. 分析: 其实一开始看见这道题我也吓傻了,k这么大,再说我又是数论鶸渣,打死也不会= = 后来看了各路神犇的题解,又仔细想了想,大概明白了. 首先,k这么大,已经不是高精乘和高精开方所能承受的了(当然,你也可以找个超级计算机算算试试) 所以我们可以把k视为∞(INF). 极限思想,由于xi互不相同,所以每个元素在比它稍微大一点点的数面前都是微乎其微,不会影响到整数部分的. (可以粗略验证

cogs 2320. [HZOI 2015]聪聪的世界

solution 6 7 8都好说 对于1 2 3 4只需自己yy一个函数就行 (ps:我把L打成l....) 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 const int N=1000006; 7 inline ll maxn(ll a,ll b){return a>b?a:b;} 8 in

[COGS 2258][HZOI 2015]复仇的序幕曲

Description 你还梦不梦痛不痛,回忆这么重你怎么背得动 ----序言 当年的战火硝烟已经渐渐远去,可仇恨却在阿凯蒂王子的心中越来越深 他的叔父三年前谋权篡位,逼宫杀死了他的父王,用铁血手腕平定了国内所有的不满 只有他一个人孤身逃了出来,而现在他组织了一只强大的军队,反攻的号角已经吹响 大战一触即发,作为他的机智又勇敢的指挥官,你必须要准确及时的完成他布置的任务 这个国家的布局是一棵树,每个城市都是树上的结点,其中每个结点上都有军队ai(人数) 树上的每条边有边权wi,表示通过这条边所需

动态树分治

感受: 就是把分治结构变成树(并不需要真正建出,只需要记录父亲) 然后每个点维护子树到该点的信息,和子树到父亲点的信息 总体来说还是很模板的一个东西 题目大概分成两类: (1)树上黑白点染色,问一个点到所有黑点的距离和 这种就是原来真正的树结构上信息修改,那么一般就是将修改的点在分治树上所在的链每个点维护的信息加加减减. (2)另一种就是询问体现动态,比如距离某个点距离<=k的点的权值和 这种问题的突破点在于原树的信息是不改变的.所以我们可以在分治树上每个点维护一个vector数组来储存信息(有

cojs 出的题目的总结

最近因为一些事情心情不太好,所以在cojs上出了几套题 (大神不要吐槽太水.. 大部分都是模板题,对模板做个总结吧,等到NOI之前还可以复习复习 今天晚上把疯狂的系列最后一道题目出完了就去切APIO了QAQ 白树黑是数学题+概率算法,不能算模板.. 动态点分治:复仇的序幕曲,树黑白 CDQ分治:决战前的黎明 双连通分量:地牢里的背叛 KD_Tree:Rikka 三分:向量vec 树链剖分:黑白树,黑树白 树上倍增:树黑白,树白黑 主席树:树白黑,黑树白 fib求循环节+矩阵乘法:疯狂的斐波那契

阿尔红军我让我特我问题沃特尔行业

http://www.houzz.com/ideabooks/38419124/thumbs/2015.01.04 http://www.houzz.com/ideabooks/38419135/thumbs/2015.01.04 http://www.houzz.com/ideabooks/38419147/thumbs/2015.01.04 http://www.houzz.com/ideabooks/38419107/thumbs/2015.01.04 http://www.houzz.c