[T2] 2019年7月16日NOIPシミュレーションゲーム折り畳まれた(倍)(動的プログラミング)

暴力\(DP \)

暴力考える\(DP \)を、我々は設定\(F_ {I、J} \) を表し、現在のオーバーレイ長\(Iは\) 第1の折り長さ\(J \)プログラムの数。

列挙は、折り畳まれた長さ転送する必要が\(K \)(\ (K \ GE J \)で)次のように、転写式です:

\ [F_ {I + 2K-J、K} + = F_ {I、J} \]

左右の場合は、初期設定に応じて、\(DP \)二回。

列挙側は時間統計計算の長さをカバーします。

最適化\(DP \)

実際に、我々は使用することができ、\(DP \)二つの配列は、左の点のための1つに分割(X \)\桁の実施形態では、他の右端が表す\(Y \)桁スキーム。

転送は、比較的単純な方程式である場合には:

\ [A_ {X + I} + = A_X、B_ {X + 2I} + = A_X \]

コード

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 10000
#define X 998244353
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int n,l,r;
class Dper
{
    private:
        int f[N+5],g[N+5],p[N+5];
    public:
        I void Solve()
        {
            #define DP(s,x,y) for(p[0]=i=1,t=n-y;i<=n;++i) p[i]=0;\
                for(i=x;2*i<=t;++i) for(j=0;2*i+j<=t;++j) Inc(p[i+j],p[j]),Inc(s[2*i+j],p[j]);++s[x];//用#define简洁表示两次DP
            RI i,j,t,ans=0;DP(f,l,r);DP(g,r,l);//DP预处理
            for(i=l;i<=n-r;++i) ans=(1LL*f[i]*g[n-i]+ans)%X,Inc(f[i+1],f[i]);printf("%d",ans);//统计答案
        }
}D;
int main()
{
    freopen("fold.in","r",stdin),freopen("fold.out","w",stdout);
    return scanf("%d%d%d",&n,&l,&r),D.Solve(),0;
}

おすすめ

転載: www.cnblogs.com/chenxiaoran666/p/Contest20190716T2.html