zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
  • 相关阅读:
    git常用命令
    Mybatis文档收集
    RocketMQ安装及配置
    vs code 插件收集
    idea中RunDashboard显示
    Error running ‘JeecgSystemApplication‘: Command line is too long. Shorten command line for JeecgSys
    shell脚本 for循环实现文件和目录遍历
    linux一次性解压多个.gz或者.tar.gz文件
    CentOS7挂载磁盘,4T磁盘挂载方法
    windows 安装Nginx服务
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12337694.html
Copyright © 2011-2022 走看看