zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营4 J 二维跑步

    https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43035417

     

    假设有i步选择不动,就有n-i步移动

    假设其中又有a步选择往右移,就有n-i-a步左移

    所以-m<=a-(n-i-a)<=m

    所以(n-m-i)/2<=a<=min{ n-i,(n+m-i)/2 }

    令g(i)=Σ C(n-i,a)(3^a)(2^(n-i-a))

    答案=Σ C(n,i)g[i]

    考虑如何递推求出g[i]

    令f(n,m)=C(n,m)(3^m)(2^(n-m))

     则3f(n-1,m-1)+2f(n-1,m)=f(n,m)

    假设n=8,m=3

    g[0]=                          f(8,3)+  f(8,4)+  f(8,5)

          =            3f(7,2)+5f(7,3)+5f(7,4)+2f(7,5)

    g[1]=              f(7,2)+  f(7,3)+  f(7,4)+  f(7,5)

          =3f(6,1)+5f(6,2)+5f(6,3)+5f(6,4)+2f(6,5)

    g[2]=              f(6,2)+  f(6,3)+  f(6,4)

          =3f(5,1)+5f(5,2)+5f(5,3)+2f(5,4)

    g[3]=  f(5,1)+  f(5,2)+  f(5,3)+  f(5,4)

    可以发现,如果已知g[i],那么将g[i]乘5,然后在搞一搞头尾就可以

    )#include<cstdio>
    #include<algorithm>
     
    using namespace std;
     
    #define N 3000001
     
    const int mod=998244353;
     
    typedef long long LL;
     
    int g[N];
    int pow2[N],pow3[N],fac[N],inv[N];
     
    int C(int n,int m)
    {
        return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
     
    int f(int n,int m)
    {
        return 1ll*C(n,m)*pow3[m]%mod*pow2[n-m]%mod;
    }
     
    int pow(int n,int m)
    {
        int s=1;
        for(;m;m>>=1,n=1ll*n*n%mod)
            if(m&1) s=1ll*s*n%mod;
        return s;
    }
     
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        pow2[0]=1;
        pow3[0]=1;
        fac[0]=1;
        inv[0]=1;
        for(int i=1;i<N;++i)
        {
            pow2[i]=pow2[i-1]*2%mod;
            pow3[i]=1ll*pow3[i-1]*3%mod;
            fac[i]=1ll*fac[i-1]*i%mod;
            inv[i]=pow(fac[i],mod-2); 
        }
        int l=0,r=0,nl,nr,ans=1;
        for(int i=n;i>=0;--i)
        {
             nl=max(0,n-m-i+1>>1);
             nr=min(n-i,m+n-i>>1);
             if(nl>l) ans=(ans-f(n-i,l++)+mod)%mod;
             while(nr>r) ans=(ans+f(n-i,++r))%mod; 
             g[i]=ans;
             ans=5ll*ans%mod;
             if(nl>=1) ans=(ans+3ll*f(n-i,nl-1)%mod)%mod;
             ans=(ans-3ll*f(n-i,nr)%mod+mod)%mod;
        }
        ans=0;
        for(int i=0;i<=n;++i) ans=(ans+1ll*C(n,i)*g[i]%mod)%mod;
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Linux实战(2):Linux传输文件
    Linux实战(1):装机一键设置脚本初级版
    Docker实战(4):Docker错误记一笔
    Docker实战(3):Tomcat部署
    Docker实战(5)升级Docker版本后的报错
    Promise
    创建数据库
    wepy中组件之间通信方法
    javascript —— 禁止通过 Enter 键提交表单
    input禁止复制、粘贴、剪切
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12335061.html
Copyright © 2011-2022 走看看