• [NOIP模拟测试9]题(Problem) 题解 (组合数全家桶+dp)


    达哥送分给我我都不要,感觉自己挺牛批。

    $type=0:$

    跟visit那题类似,枚举横向移动的步数直接推公式:

    $ans=sum C_n^i imes C_i^{frac{i}{2}} imes C_{n-i}^{frac{n-i}{2}},i\% 2=0$

    $type=1:$

    因为不能触碰负半轴,所以可以把右移看成+1,左移看成-1,转化为前缀和大于等于0的问题

    于是直接Catalan数就好了。注意是第$frac {n}{2}$项的Catalan。

    $Catalan_n=C_{2n}^{n}-C_{2n}^{n-1}$

    $type=2:$

    观察到数据范围较小,考虑dp。

    设$f[i]$为走i步回到原点的方案数,通过枚举第一次回到原点的步数j进行转移。

    显然j只能为偶数。

    $f[i]=sum f[i-j]*Catalan(frac{j}{2}-1)$

    $type=3:$

    还是枚举横向走的步数,结合Catalan数求解。

    $ans=sum C_n^i*Catalan(frac{i}{2})*Catalan(frac{n-i}{2})$

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll mod=1000000007;
    const int N=100005;
    int n,op;
    ll fac[N<<1],ans,dp[N<<1];
    ll qpow(ll a,ll b)
    {
        ll res=1;//a%=mod;
        while(b)
        {
            if(b&1)res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    ll ini()
    {
        fac[0]=1;
        for(int i=1;i<=(N-5)<<1;i++)
            fac[i]=1LL*i*fac[i-1]%mod;
    }
    ll C(ll x,ll y)
    {
        if(y>x)return 0;
        return fac[x]*qpow(fac[y],mod-2)%mod*qpow(fac[x-y],mod-2)%mod;
    }
    ll lucas(ll x,ll y)
    {
        if(!y)return 1;
        return C(x%mod,y%mod)*lucas(x/mod,y/mod)%mod;
    }
    ll Catalan(ll x)
    {
        return (lucas(x*2,x)-lucas(x*2,x-1)+mod)%mod;
    }
    void qj1()
    {
        //cout<<2*n<<endl;
        //cout<<C(2*n,n)<<endl;
        ans=Catalan(1LL*n/2);
        cout<<ans<<endl;
    }
    void qj0()
    {
        for(int i=0;i<=n;i++)
        {
            if(i%2)continue;
            ans+=lucas(1LL*n,1LL*i)%mod*lucas(1LL*i,1LL*i/2)%mod*lucas(1LL*(n-i),1LL*(n-i)/2)%mod,ans%=mod;
        }
        cout<<ans<<endl;
    }
    void qj3()
    {
        for(int i=0;i<=n;i++)
        {
            if(i%2)continue;
            ans+=lucas(1LL*n,1LL*i)*Catalan(1LL*i/2)%mod*Catalan(1LL*(n-i)/2)%mod,ans%=mod;
        }
        cout<<ans<<endl;
    }
    void qj2()
    {
        dp[0]=1;
        for(int i=2;i<=n;i+=2)
            for(int j=2;j<=i;j+=2)
                dp[i]+=dp[i-j]*4%mod*Catalan(1LL*j/2-1LL)%mod,dp[i]%=mod;
        cout<<dp[n]<<endl;
    }
    int main()
    {
        scanf("%d%d",&n,&op);
        ini();
        if(op==1)qj1();
        else if(op==0)qj0();
        else if(op==3)qj3();
        else qj2();
        return 0;
    }
  • 相关阅读:
    大道至简读后感
    机器学习十讲(一)
    第一个TensorFlow的简单例子
    初识深度学习
    如何使用本地的Navicat连接服务器中的Mysql
    阿里云ECS-安装Tomcat
    阿里云ECS-CentOS 8上安装MySQL 8.0
    阿里云ECS--CentOS8安装jdk1.8
    进度报告十(重大技术需求)
    进度报告九 (重大技术需求调研)
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11267549.html
Copyright © 2020-2023  润新知