【LOJ#6074】子序列(动态规划)

题面

LOJ

题解

考虑一个暴力\(dp\)。

设\(f[i][c]\)表示当前在第\(i\)位,并且以\(c\)结尾的子序列个数。

那么假设当前位为\(a\),强制把\(a\)接在所有出现过的子序列后面,再加上一个单独的\(a\)。

也就是\(f[i][a]=\sum_j f[i-1][j]\),其他的\(f[i][k]=f[i-1][k]\)。

显然这样一个转移是可以写成矩阵形式的,预处理矩阵的前缀和和矩阵逆的前缀和就可以很方便的计算答案,这样子的复杂度是字符集大小三方的。

发现我们要的只是一个行向量或者一个列向量。这样子可以优化单次矩乘为字符集大小平方,然而我们直接按照\(dp\)转移就好了,就变成了字符集大小了。

那么最终的答案就是一个行向量和一个列向量相乘即可。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MOD 1000000007
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
char s[MAX];
int n,Q;
int a[10][10],S[10],L[MAX][10],R[MAX][10];
int main()
{
scanf("%s",s+1);n=strlen(s+1);Q=read();
for(int i=0;i<=9;++i)a[i][i]=S[i]=R[0][i]=1;
for(int i=1;i<=n;++i)
{
int c=s[i]-96,tmp;
for(int j=0;j<=9;++j)tmp=a[j][c],a[j][c]=S[j],S[j]=(2ll*S[j]-tmp+MOD)%MOD;
for(int j=0;j<=9;++j)R[i][j]=S[j];
}
memset(a,0,sizeof(a));memset(S,0,sizeof(S));
for(int i=0;i<=9;++i)a[i][i]=1,L[0][i]=!i;
for(int i=1;i<=n;++i)
{
int c=s[i]-96,tmp;
for(int j=0;j<=9;++j)tmp=(a[c][j]+S[j])%MOD,S[j]=(S[j]-tmp+MOD)%MOD,a[c][j]=(a[c][j]+tmp)%MOD;
for(int j=0;j<=9;++j)L[i][j]=(a[0][j]+S[j])%MOD;
}
while(Q--)
{
int l=read(),r=read(),ans=MOD-1;
for(int i=0;i<=9;++i)ans=(ans+1ll*R[r][i]*L[l-1][i])%MOD;
printf("%d\n",ans);
}
return 0;
}

【LOJ#6074】子序列(动态规划)的更多相关文章

  1. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  2. LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)

    题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...

  3. loj#6074. 「2017 山东一轮集训 Day6」子序列(矩阵乘法 dp)

    题意 题目链接 Sol 设\(f[i][j]\)表示前\(i\)个位置中,以\(j\)为结尾的方案数. 转移的时候判断一下\(j\)是否和当前位置相同 然后发现可以用矩阵优化,可以分别求出前缀积和逆矩 ...

  4. hdu1231最大连续子序列(动态规划)

    最大连续子序列 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  5. HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)

    6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...

  6. 【ACM】最长公共子序列 - 动态规划

    最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...

  7. 最长上升子序列(动态规划递推,LIS)

    1759:最长上升子序列 题目: 总时间限制: 2000ms 内存限制: 65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的 ...

  8. C++求解汉字字符串的最长公共子序列 动态规划

        近期,我在网上看了一些动态规划求字符串最长公共子序列的代码.可是无一例外都是处理英文字符串,当处理汉字字符串时.常常会出现乱码或者不对的情况. 我对代码进行了改动.使用wchar_t类型存储字 ...

  9. [LeetCode] 300. 最长上升子序列 ☆☆☆(动态规划 二分)

    https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/dong-tai-gui-hua-she-ji-fan ...

随机推荐

  1. 蒲公英App开发之检测新版本

    https://www.jianshu.com/p/2d3f048511d7 2017.04.17 16:22* 字数 62 阅读 422评论 0喜欢 1 可以在App内部实现检测版本更新并实现安装. ...

  2. ElastichSearch漏洞

    Ubuntu服务器被黑经历(ElastichSearch漏洞) 起因 最近我们的一台Ubuntu阿里云服务器一直提示有肉鸡行为,提示了好几天,开始并没有关注,然后连续几天后发现应该是个大问题啊.很可能 ...

  3. 快速失败/报错机制 - fail-fast

    一.快速报错机制(fail-fast) 这是<Java编程思想>中关于快速报错机制的描述 Java容器有一种保护机制,能够防止多个进程同时修改同一个容器的内容.如果在你迭代遍历容器的过程中 ...

  4. 学习yii2.0——事件

    参考:https://www.yiichina.com/doc/guide/2.0/concept-events 事件 yii框架中的事件定义和JavaScript中的事件定义差不多:为某个事件绑定一 ...

  5. Linux Centos 迁移Mysql 数据位置

    Linux Centos 迁移Mysql 数据位置 由于业务量增加导致安装在系统盘(20G)磁盘空间被占满了, 现在进行数据库的迁移. Mysql 是通过 yum 安装的. Centos6.5Mysq ...

  6. Farm Irrigation

    题目:Farm Irrigation 题目链接:http://210.34.193.66:8080/vj/Problem.jsp?pid=1494 题目思路:并查集 #include<stdio ...

  7. vue中的跨域问题

    https://segmentfault.com/a/1190000011072725(原文)   使用vue-axios和vue-resource解决vue中调用网易云接口跨域的问题 注(api很重 ...

  8. Granfana+PostgreSQL

    建表: create table pdm_log( id serial primary key, date_time timestamp with time zone DEFAULT CURRENT_ ...

  9. HTML4到HTML5

    第一步: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0.1//EN" "http://www.w3.org/TR/html ...

  10. python之路--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...