准队爷富榄出的题目,被虐的不要不要的,打了个40分还被卡常。。。
题意:给你1个长度为n的字符串,每次给出询问l,r问l,r中有多少个本质不同的子序列。
n,q<=1e5。
一开始差点连题目都没理解清楚,子序列一定不连续,子串才连续= =。。
一个并不显然的dp是设f[i][j]表示第i位为j的答案,那么初始f[i][s[i]]=1,然后f[i][j]+=sigma(f[i][1-9]),然后我们发现好像这个跟i的关系不太大,然后把第一维舍去,变成f[i],那么很明显,n^2的做法就是每次枚举l,r之间的时候ans=sigma(f[i]),f[i]=sigma(f[j])(j=1-9),然后可能我姿势不对被卡了10分。。
然后我就不大会了,后来看了题解发现自己是个煞笔。
为什么不设一个能递推的呢???
考虑如何求一个序列的子序列个数,有一个简单的 Dp 转移
若 S[i]=c,则F[i][c] = ∑F[i − 1][k], F[i][k] = F[i − 1][k],
这个很明显可以用矩阵加速= =
统计前缀积和逆矩阵的前缀积,然后答案用两个前缀积搞搞就好了。
注意预处理的地方。
然后就是富榄说矩阵乘法改变一下j,k的顺序可以做到寻址优化,蒙蔽了= =而且居然真的快了100多ms。。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using