[COGS2287][HZOI2015]疯狂的机器人(NTT+Catalan数)

标签: NTT Catalan数列
8人阅读 评论(0) 收藏 举报
分类:

题目:

我是超链接

题解:

又是上下左右走的问题。。。当初我的Catalan入门就是这玩意

那么我们设g[i]表示走i步光走左右不走上下,不会不走,回到原点的方案数
可以发现当i为奇数的时候g[i]=0
考虑i为偶数的情况,肯定是选择i/2步向上走,i/2步向下走,并且时刻保证向上走的步数>=向下走的步数
这不就是Catalan数吗,可以用Cii/2Cii/21求解

显然光走上下不走左右,不会不走,回到原点的方案也是g[i]

现在我们设f[i]表示走i步,可以走上下左右,不会不走,回到原点的方案数
那么f[i]=j=0ig(j)g(ij)Cij
我们把组合数展开

f[i]=j=0ig(j)j!g(ij)(ij)!i!

卷积!又看到了熟悉的模数,NTT吧
那么如果有不走的情况呢?ans=i=0nf[i]Cni

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int N=400005;
LL a[N],b[N],mul[N],inv[N],invmul[N],g[N];int r[N],n;
LL ksm(LL a,LL k)
{
    LL ans=1;
    for (;k;k>>=1,a=a*a%mod)
      if (k&1) ans=ans*a%mod;
    return ans;
}
void NTT(LL *a,int id)
{
    for (int i=0;i<n;i++)
      if (i<r[i]) swap(a[i],a[r[i]]);
    for (int k=1;k<n;k<<=1)
    {
        LL wn=ksm(3,(mod-1)/(k<<1));
        for (int i=0;i<n;i+=(k<<1))
        {
            LL w=1;
            for (int j=0;j<k;j++,w=w*wn%mod)
            {
                LL x=a[i+j],y=w*a[i+j+k]%mod;
                a[i+j]=(x+y)%mod; a[i+j+k]=(x-y+mod)%mod;
            }
        }
    }
    if (id==-1) reverse(a+1,a+n);
}
LL C(int n,int m)
{
    if (m>n) return 0;
    return mul[n]*invmul[m]%mod*invmul[n-m]%mod;
}
void init(int n)
{
    mul[0]=mul[1]=1;
    for (int i=2;i<=n;i++) mul[i]=mul[i-1]*i%mod;
    inv[1]=1;
    for (int i=2;i<=n;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    invmul[0]=1;
    for (int i=1;i<=n;i++) invmul[i]=invmul[i-1]*inv[i]%mod;
    for (int i=0;i<=n;i+=2) 
      g[i]=(C(i,i/2)-C(i,i/2+1)+mod)%mod;
    g[0]=1;
    for (int i=0;i<=n;i++) a[i]=b[i]=g[i]*invmul[i]%mod;
}
int main()
{
    freopen("crazy_robot.in","r",stdin);
    freopen("crazy_robot.out","w",stdout);
    int fn;scanf("%d",&fn);init(fn);
    int L=0;
    for (n=1;n<=fn*2;n<<=1) L++;
    for (int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<L-1);
    NTT(a,1); NTT(b,1);
    for (int i=0;i<=n;i++) a[i]=a[i]*b[i]%mod;
    NTT(a,-1);LL inv=ksm(n,mod-2);
    for (int i=0;i<=n;i++) a[i]=a[i]*inv%mod;
    for (int i=0;i<=fn;i++) a[i]=a[i]*mul[i]%mod;
    LL ans=0;
    for (int i=0;i<=fn;i++) ans=(ans+a[i]*C(fn,i)%mod)%mod;
    printf("%lld",ans);
}
查看评论

2002年苹果公司突出新闻

 Next Years News As a service to our readers who have better things to do than to read the stupid ne...
  • jokerman
  • jokerman
  • 2002-01-30 12:03:00
  • 673

[COGS2287][HZOI 2015]疯狂的机器人(NTT+组合数学)

题目描述传送门题解本来是想找一道题想一想dp到底是怎么用FFT优化的,然而写完了发现怎么和dp没啥关系呢 也可能是我太弱根本没看出来dp 不过确实是一道好题!在hxy神犇的一些提示下做出来…令g(...
  • Clove_unique
  • Clove_unique
  • 2017-03-09 21:50:01
  • 526

NKOJ 4028(HZOI 2015)疯狂的机器人(NTT+卡特兰数)

P4028[HZOI 2015]疯狂的机器人 问题描述 现在在二维平面内原点上有一只机器人 他每次操作可以选择向右走,向左走,向下走,向上走和不走(每次如果走只能走一格) ...
  • Mogician_Evian
  • Mogician_Evian
  • 2018-03-05 23:22:32
  • 43

[COGS2287][HZOI 2015]疯狂的机器人(NTT)

Loli今天下午还要考试差评= =
  • FromATP
  • FromATP
  • 2017-04-04 10:30:19
  • 472

cogs 2287. [HZOI 2015]疯狂的机器人 (NTT优化DP)

题目描述 [HZOI 2015]疯狂的机器人 ★★★ 输入文件:crazy_robot.in 输出文件:crazy_robot.out 简单对比 时间限制:1 s 内存限制:512...
  • clover_hxy
  • clover_hxy
  • 2017-02-23 22:00:10
  • 697

微信疯狂数钱

  • 2014年10月29日 09:54
  • 237KB
  • 下载

COGS 2123. [HZOI 2015] Glass Beads

最小表示法,这里用后缀自动机实现。 刚刚学了后缀自动机,懵逼中。#include #include #include #include #include using namespace std; c...
  • magic_sheep
  • magic_sheep
  • 2017-03-06 21:00:33
  • 163

hzoi2015(ntt+组合数学)

首先,对于行和列我们可以分别考虑,且行列式等价的,那么我们可以考虑将行的方案和列的方案求个卷积。 #include #include #include #include #include u...
  • zhhx2001
  • zhhx2001
  • 2017-04-01 11:01:15
  • 452

黑马程序员——C基础之疯狂猜数游戏

#include #include int main(int argc, const char * argv[]) {     //int i = 0;     //while (i...
  • xiaohei3576
  • xiaohei3576
  • 2015-12-07 11:22:21
  • 333

nao机器人抓取程序

  • 2016年07月10日 10:27
  • 4KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 7万+
    积分: 7541
    排名: 3624
    最新评论