题目描述

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. java爬虫系列第三讲-获取页面中绝对路径的各种方法

    在使用webmgiac的过程中,很多时候我们需要抓取连接的绝对路径,总结了几种方法,示例代码放在最后. 以和讯网的一个页面为例: xpath方式获取 log.info("{}", ...

  2. jenkins实现以gitlab为代码仓库的构建

    简介 前一篇随笔是安装jenkins的过程,比较简单,这一次说一下用jenkins配置以gitlab为代码管理仓库的maven项目的完整个构建过程,以及我碰到的一些问题.由于是maven项目,所以我们 ...

  3. 程序员50题(JS版本)(七)

    程序31:有一个已经排好序的数组.现输入一个数,要求按原来的规律将它插入数组中 var test=[213,134,134,84,62,11]; const num=33; test.push(num ...

  4. React-组件的生命周期详解(含React16版本)

    在一个组件的整个生命周期中,通过用户的交互来更新state或者props,重新渲染组件,更新页面的ui.组成一个简单的"状态机". react的生命周期三个阶段: Mounting ...

  5. Doctype的作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义?

    Doctype作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义? 1.1 Doctype作用 <!DOCTYPE>声明叫做文件类型定义(DTD),声明的作用为了告诉浏览器该 ...

  6. OPPO realme 2在哪里打开Usb调试模式的简单步骤

    每当我们使用PC通过数据线链接到安卓手机的时候,如果手机没有开启USB调试模式,PC则没能成功识别我们的手机,这时我们需要找解决方法将手机的USB调试模式开启,下文我们记录一下OPPO realme ...

  7. android使用百度地图最新sdk5.0后后代码混淆时,地图无法显示闪退问题

    描述:刚开始遇到这个问题我一步一步去排除,最后发现在初始化地图的时候,代码混淆就有问题了, 问题描述:当跳显示地图的页面APP闪退, 解决对比: 1:对于老版本百度sdk:代码混淆时语句: -libr ...

  8. Android Studio 添加引用Module项目

    新建Android项目,修改为Module 新建一个android项目 给项目命名,这里命名为MyLibrary,作为可引用的Module项目 点击下一步,选择一个Activity,点击ok 下面将这 ...

  9. deepin linux 学习笔记(二)——文本编辑器

    目录 deepin linux 学习笔记(二)--文本编辑器 前言 nano 小巧的命令行编辑器 通用 编辑 定位 排版 配置 vim 思路独特的超级编辑器 命令模式 插入模式 底线模式(末行模式) ...

  10. C#中++i与i++的区别

    日常编程中经常用到++i与i++,知识点虽然很小,但有时候会犯迷糊,在这里小小的记录一下. ++i 即前递增,顾名思义也就是先自增后传值: 举个栗子 int i=5; int j=++i; 此时i的值 ...