题目描述

https://loj.ac/problem/6074

题解

对于子序列的dp,我们可以设置一个dp。

我们设dp[i]表示以i这个字符结尾的子序列个数,转移为dp[i]+=∑dp[k]-dp[i]。其实我们发现这样等价于dp[i]=∑dp[k]。

另外我们还要再设一个空字符的位置表示空字符,所以我们的转移矩阵长成这样。

1 0 1 0 0

0 1 1 0 0

0 0 1 0 0

0 0 1 1 0

0 0 1 0 1

我们一开始是空的,所以转移矩阵为

0 0 0 0 1

最后我们要归为一个答案,所以还要乘上一个列矩阵。

1

1

1

1

0

直接做是N^3的,我们发现这个矩阵长得非常有特点,我们把它的逆矩阵求出来之后发现。

1 0 -1 0 0

0 1 -1 0 0

0 0 1 0 0

0 0 -1 1 0

0 0 -1 0 1

所以我们的思路就是让行向量*1~l-1的逆矩阵再乘上1~r的正矩阵,在乘上列矩阵。

对于正矩阵和逆矩阵的部分我们可以分开维护。

对于正矩阵的右乘的过程,我们可以维护每一行的和,因为每次的乘法相当于把ch位变成这一行的和,所以就直接维护就好了。

注意我们维护的是最后做完之后再乘上一个列矩阵,所以维护的时候只需要维护矩阵和矩阵乘列向量的值就好了。

对于逆矩阵的左乘,我们考虑它实际上是把当前列的第ch位减掉,而且它是对每个列除了ch行都批量的减掉,所以我们维护一下每一列的加法标记就好了。

同样我们也是要维护乘完之后再去乘上行向量的答案。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define M 11
#define N 100002
using namespace std;
const int mod=1e9+;
char s[N];
int sum[M],n,c,now[M][M],val[N],nowl[N][M],nowr[N][M],tag[M];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
int main(){
scanf("%s",s+);n=strlen(s+);
c=;
for(int i=;i<=c;++i)sum[i]=,nowr[][i]=,now[i][i]=;
nowr[][c]=;
for(int i=;i<=n;++i){
int x=s[i]-'a';
for(int j=;j<=c;++j)
val[j]=now[j][x],now[j][x]=sum[j];
for(int j=;j<=c;++j)sum[j]=(1ll*sum[j]*-val[j]+mod)%mod;
for(int j=;j<=c;++j)nowr[i][j]=(1ll*sum[j]-now[j][c]+mod)%mod;
}
nowl[][c]=;
memset(now,,sizeof(now));
for(int i=;i<=c;++i)now[i][i]=;
for(int i=;i<=n;++i){
int x=s[i]-'a';
for(int j=;j<=c;++j)val[j]=(now[x][j]+tag[j])%mod;
for(int j=;j<=c;++j)now[x][j]=(now[x][j]+val[j])%mod,tag[j]=(tag[j]-val[j]+mod)%mod;
for(int j=;j<=c;++j)nowl[i][j]=(now[c][j]+tag[j])%mod;
}
int q=rd();int l,r;
while(q--){
l=rd();r=rd();int ans=;
for(int i=;i<=c;++i)(ans+=1ll*nowr[r][i]*nowl[l-][i]%mod)%=mod;
printf("%d\n",ans);
}
return ;
}

LOJ子序列的更多相关文章

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

    [LOJ#6074]子序列(动态规划) 题面 LOJ 题解 考虑一个暴力\(dp\). 设\(f[i][c]\)表示当前在第\(i\)位,并且以\(c\)结尾的子序列个数. 那么假设当前位为\(a\) ...

  2. [科技]Loj#6564-最长公共子序列【bitset】

    正题 题目链接:https://loj.ac/p/6564 题目大意 给两个序列\(a,b\)求它们的最长公共子序列. \(1\leq n,m,a_i,b_i\leq 7\times 10^4\) 解 ...

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

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

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

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

  5. 【刷题】LOJ 6005 「网络流 24 题」最长递增子序列

    题目描述 给定正整数序列 \(x_1 \sim x_n\) ,以下递增子序列均为非严格递增. 计算其最长递增子序列的长度 \(s\) . 计算从给定的序列中最多可取出多少个长度为 \(s\) 的递增子 ...

  6. 【LOJ】#2265. 「CTSC2017」最长上升子序列

    题解 点了一个新技能叫杨表(事实上集训的时候听过,但是一直不会 这道题就是让我们找到k个不上升子序列,要求长度加和最大 我们用杨表去维护,但是由于杨表的行数可能是n的,复杂度会炸 我们只维护前\(\s ...

  7. 【LOJ】#2172. 「FJOI2016」所有公共子序列问题

    题解 听说是什么序列自动机? 我们考虑对于每个位置的串,下面拼接相同的字符时,拼接最近的一个,这样可以保证不重不漏 为了实现这个我们需要什么呢,我们需要一个链表,记录一下每个位置的下一个字符会转移到哪 ...

  8. LOJ 2172 「FJOI2016」所有公共子序列问题——序列自动机

    题目:https://loj.ac/problem/2172 在两个序列自动机上同时走,这样暴搜. 先走字典序小的字符,一边搜一边输出,就是按字典序排序的. 方案数很多,需要高精度?空间很小,要压位. ...

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

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

随机推荐

  1. 一个tomcat设置多个端口,多个端口对应多个应用

    修改tomcat/conf目录里面server.xml文件 例如下面这样新增一个8090端口,设置下appBase目录,这样就可以用一个tomcat监听多个端口,每个端口都可以放应用了.我这样新增下面 ...

  2. java爬虫系列第一讲-爬虫入门

    1. 概述 java爬虫系列包含哪些内容? java爬虫框架webmgic入门 使用webmgic爬取 http://ady01.com 中的电影资源(动作电影列表页.电影下载地址等信息) 使用web ...

  3. PHP信号管理

    PHP信号管理   SIGHUP     终止进程     终端线路挂断 SIGINT     终止进程     中断进程 SIGQUIT    建立CORE文件终止进程,并且生成core文件 SIG ...

  4. K3实现按虚拟件/组件发料

           最近公司调度部反应了一个K3使用过程中遇到的巨大问题:公司成品BOM组成物料种类破千,绝大部分还不能拆分成组件.为了方便区分,从逻辑上把一堆堆的半成品分成了一个个虚拟件.K3生成的投料单 ...

  5. Android Studio Error:Execution failed for task ':app:preDebugAndroidTestBuild'.彻底解决的方法以及修改AScompileSDKVersion

    Error Error:Execution failed for task ':app:preDebugAndroidTestBuild'. > Conflict with dependency ...

  6. 巧用Handler获取View控件信息

    众所周知,在Android实际开发中,对于某些复杂多变的情况,控件的位置摆放.大小控制并非是xml类型的layout文件完全可以搞定的.此时,我们通常会使用Java代码来通过动态计算,将指定的控件摆放 ...

  7. 码云代码托管平台与TortoiseSVN的使用

    1.到https://gitee.com/进行注册,然后登陆 可以发现可以将项目设为私有 2.下载tortoisesvn,一路next安装即可 3.项目创建 4.下载项目 5.创建文件并提交 6.如何 ...

  8. sqlserver数据库NULL类型注意事项

    1,变量NULL类型赋值需要初始化 2,判断条件

  9. RocketMQ4.3.X关于设置useEpollNativeSelector = true报错问题

    前一阵子刚整理完RocketMQ4.3.x版本的相关配置的工作,接下来就来测试一下改变参数会带来什么好的结果 首先我就选中了useEpollNativeSelector 这个参数 默认这个参数是 fa ...

  10. 编辑器之神-vim的使用

    vim即vi的升级版:在linux中,vi是vim的软链接,我们敲vi和vim出来的都是vim: 纯手打,如有错误,敬请指出. vi的三种模式及简单使用 vi三种模式 命令模式(默认):是文件的入口, ...