• 洛谷P4590 [TJOI2018]游园会


    题目描述

    题解

    首先我们考虑如果我们知道了原串,那我们要求两个串的 $ ext{Lcs}$ 的长度就是 $ ext{dp}$ : $f[i][j]$ 表示 $S$ 串到 $i$ , $T$ 串到 $j$ 的 $ ext{Lcs}$ 长度,考虑转移: $f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]+[S[i]==T[j]])$ ,我们可以发现 $f[i][j]-f[i][j-1]in {0,1}$ 。回到原题,我们可以做 $ ext{dp}$ : $F[i][S][0/1/2]$ 表示已经放完了前 $i$ 个位置,如果把前面的位置和匹配串拿去做 $f$ 的 $ ext{dp}$ 的话, $f[i]$ 的差分数组组成的状态为 $S$ ,最后 $0/1/2$ 个字母是和 $NOI$ 的前几个字母是一样的的方案数。在此之前我们可以预处理出 $g[S][c]$ 表示目前差分数组的状态为 $S$ ,放入 $c$ 后新的差分数组的状态。考虑转移的话就枚举下一个位置放什么字母即可。效率: $O(n2^k)$ 。

    考虑从假设我们已经知道了题目中的某个信息,如何求答案入手,可能可以得到正解。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1<<15,P=1e9+7;
    int n,k,m,g[N][3],a[20],b[20],X,Y=1,t[N],s[20],f[2][N][3];
    char h[20],d[5]="NOI";
    int get(int s,int c){
        for (int i=1;i<=k;i++)
            a[i]=a[i-1]+(s&1),s>>=1;
        for (int i=1;i<=k;i++)
            b[i]=max(max(b[i-1],a[i]),
                a[i-1]+(d[c]==h[i]));
        for (int i=k;i;i--)
            s<<=1,s|=(b[i]-b[i-1]);
        return s;
    }
    int main(){
        scanf("%d%d%s",&n,&k,h+1);
        m=1<<k;f[0][0][0]=1;
        for (int i=0;i<m;i++)
            for (int c=0;c<3;c++)
                g[i][c]=get(i,c);
        for (int i=1;i<=n;i++){
            memset(f[Y],0,sizeof f[Y]);
            for (int j=0;j<m;j++)
                for (int k=0,o;k<3;k++)
                    for (int c=0;c<3;c++){
                        if (!c) o=1;
                        else if (c<2) o=k==1?2:0;
                        else o=k==2?3:0;
                        if (o==3) continue;
                        (f[Y][g[j][c]][o]+=f[X][j][k])%=P;
                    }
            X^=1,Y^=1;
        }
        for (int i=0;i<m;i++){
            t[i]=t[i>>1]+(i&1);
            for (int j=0;j<3;j++)
                (s[t[i]]+=f[X][i][j])%=P;
        }
        for (int i=0;i<=k;i++) printf("%d
    ",s[i]);
        return 0;
    }
  • 相关阅读:
    C# 获取文件的修改时间、访问时间、创建时间
    Nhibernate Or多条件查询
    C# 将GridView当前页数据导成Execl
    C# 清空文件夹
    TreeView默认收缩
    JS控制控件的隐藏显示
    div置顶,不随滚动条滚动而滚动
    js 父窗体与子窗体的调用
    树形菜单的绑定以及链接
    2010.10.16 OA项目组一周报告 CQ
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12337694.html
Copyright © 2020-2023  润新知