BZOJ 5336:[TJOI2018]パーティーDpをDpとスリーブ

タイトル

\(〜\)
BZOJ 5336
LUOGU 4590
説明

小豆は、NOIのガーデンパーティー、会議室に参加し、金メダルを得るでしょう、それぞれ完成したプロジェクトは、メダルが唯一のN、O、I、言葉になります。会議室では、彼はKメダルからなる文字列を収集しました。
表彰規則は、文字列の最長共通部分列の長さと小豆の報酬レベルの最後の文字列としてメダルを授与します。
現在知られている文字列の長さを授与することはNであり、表彰メダルにNOIの三つの連続する文字列を表示されない、すなわち、メダルサブNOIには表示されません。
小豆は現在、さまざまな法的授与のボーナスレベルは、各文字列に対応しますどのように多くを知りたいです。

入力

最初の2つの行番号、列のキャッシング、小豆収集メダル長の長さを表すN、K列。
小豆列を示すK個の文字の合計の2行目のメダルを得ました。
N <= 1000&K <= 15

出力

K + 1つのラインの合計は、i行目は、I-1正当Duijiangの異なるストリングの数小豆最終ボーナスレベルで表され、この数は、10 ^ 7 + 9 MODの結果重要であろう。

サンプル入力

3 2
NO

サンプル出力

。1
19
。6
プロンプト
最長共通部分列の文字列の長さ0である:III、
最長の文字列の共通部分列の長さは2である:NON、NNO、NOO、ONO 、INO、NIO、
NOIを除去し、残りの19(26-6 -1)1の最長共通部分列の長さの種類。

分析

そして、実際に問題があることを発見し3864をBZOJ表示されないことができ、制限のようにただ1層以上\(NOI \)文字を、我々は多状態の一次元最初の2000万人を記録を設定します。

コードの具体的な外観は、彼から学ぶことができます。

コード

#include<bits/stdc++.h>
using namespace std;
const int maxk=16,mod=1e9+7;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

typedef int iarr[maxk+1];
iarr a,f,g,ans;
int v[1<<maxk][3],w[3][3];
int F[2][1<<maxk][3];
char ch[maxk+1];
int main()
{
    int n,m;read(n);read(m);
    scanf("%s",ch+1);
    for (int i=1; i<=m; ++i)
    {
        if (ch[i]=='N') a[i]=0;
        if (ch[i]=='O') a[i]=1;
        if (ch[i]=='I') a[i]=2;
    }
    for (int i=0; i<(1<<m); ++i)
    {
        for (int j=0; j<m; ++j) f[j+1]=f[j]+(i>>j&1);
        for (int j=0; j<3; ++j)
        {
            for (int k=1; k<=m; ++k)
                if (a[k]==j) g[k]=f[k-1]+1;
                else g[k]=max(f[k],g[k-1]);
            v[i][j]=0;
            for (int k=1; k<=m; ++k)
                if (g[k]>g[k-1]) v[i][j]|=1<<(k-1);
        }
    }
    w[0][0]=1,w[0][1]=0,w[0][2]=0;
    w[1][0]=1,w[1][1]=2,w[1][2]=0;
    w[2][0]=1,w[2][1]=0,w[2][2]=3;
    for (int j=0; j<(1<<m); ++j)
        for (int l=0; l<3; ++l) F[0][j][l]=0;
    int x=0;F[0][0][0]=1;
    for (int i=0; i<n; ++i,x^=1)
    {
        for (int j=0; j<(1<<m); ++j)
            for (int l=0; l<3; ++l) F[x^1][j][l]=0;//memset(F[x^1],0,sizeof(F[x^1]));
        for (int j=0; j<(1<<m); ++j)
            for (int l=0; l<3; ++l) if (F[x][j][l])
                for (int k=0; k<3; ++k)
                    if (w[l][k]<3) F[x^1][v[j][k]][w[l][k]]=(F[x^1][v[j][k]][w[l][k]]+F[x][j][l])%mod;
    }
    for (int i=0,v; i<(1<<m); ++i)
    {
        v=__builtin_popcount(i);
        for (int l=0; l<3; ++l) ans[v]=((long long)ans[v]+F[x][i][l])%mod;
    }
    for (int i=0; i<=m; ++i) write(ans[i]),puts("");
    return 0;
}

おすすめ

転載: www.cnblogs.com/G-hsm/p/11318560.html