2019/1/18 UPD:
【JZOJ 6008】Sequence是【JZOJ 5132】 子序列 的升级版,令串长为N,则N<=1e5,而前者字符集|c|<=52,后者|c|<=10
也即:问题“Q次询问长度为N的串S的子串S[l…r]中本质不同子序列个数”,强制在线,可以做到
O
(
n
∣
c
∣
)
O(n|c|)
O(n∣c∣)预处理+单次询问
O
(
∣
c
∣
)
O(|c|)
O(∣c∣)的复杂度
Description
40%
dp,很简单所以不说了
100%
小写字母只有前9个,考虑抓住这个突破口
仔细观察dp式子
f
[
i
]
[
s
[
i
]
]
=
1
+
∑
c
h
f
[
i
−
1
]
[
c
h
]
f[i][s[i]]=1+\sum_{ch}f[i-1][ch]
f[i][s[i]]=1+∑chf[i−1][ch]
f
[
i
]
[
c
h
]
=
f
[
i
−
1
]
[
c
h
]
f[i][ch]=f[i-1][ch]
f[i][ch]=f[i−1][ch]
这可以写成矩阵的形式,我们可以预处理出矩阵前缀积,逆矩阵前缀积
O
(
n
1
0
3
+
q
1
0
2
)
O(n10^3+q10^2)
O(n103+q102)
Code
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
#define mset(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef ll mat[10][10];
const int N=1e5+5,mo=1e9+7;
int n,s[N];
ll A[10],B[10],C[10];
mat f[N],inv[10],g[N],cmat[10];
void read(int &t)
{
t=0;int p=1;char ch;
for(ch=getchar();ch<'0' || ch>'9';ch=getchar())if(ch=='-') p=-1;
for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';t*=p;
}
ll qmi(ll x,ll n)
{
ll t=1;
for(;n;n>>=1,x=x*x%mo)
if(n&1) t=t*x%mo;
return t;
}
void mul(mat &c,mat a,mat b)
{
mset(c,0);
fo(i,0,9)
fo(j,0,9)
fo(k,0,9) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mo;
}
void getinv(mat &c,mat b)
{
mset(c,0);fo(i,0,9) c[i][i]=1;
mat a;memcpy(a,b,sizeof(a));
fo(i,0,9)
{
int p=-1;
fo(j,i,9)
if(a[j][i]) {p=j;break;}
swap(a[i],a[p]),swap(c[i],c[p]);
ll ny=qmi(a[i][i],mo-2);
fo(j,i+1,9)
{
ll t=mo-a[j][i]*ny%mo;
fo(k,i,9) a[j][k]=(a[j][k]+t*a[i][k])%mo,c[j][k]=(c[j][k]+t*c[i][k])%mo;
}
}
fd(i,9,0)
{
ll ny=qmi(a[i][i],mo-2);
fo(j,0,i-1)
{
ll t=mo-a[j][i]*ny%mo;
fo(k,i,9) a[j][k]=(a[j][k]+t*a[i][k])%mo,c[j][k]=(c[j][k]+t*c[i][k])%mo;
}
}
}
int main()
{
freopen("sub9.in","r",stdin);
freopen("sub.out","w",stdout);
for(char ch=getchar();'a'<=ch && ch<='z';ch=getchar()) s[++n]=ch-'a';
fo(ch,0,8)
fo(i,0,9) cmat[ch][i][i]=cmat[ch][i][ch]=1;
fo(i,0,9) f[0][i][i]=inv[0][i][i]=g[0][i][i]=1;
fo(i,1,n) mul(f[i],f[i-1],cmat[s[i]]);
//fo(i,1,n) getinv(inv[i],f[i]);
fo(i,0,8) getinv(inv[i],cmat[i]);
fo(i,1,n) mul(g[i],inv[s[i]],g[i-1]);
int l,r,Q;
read(Q);
while(Q--)
{
read(l),read(r);
mset(A,0);A[9]=1;
mset(B,0);
fo(j,0,9)
fo(k,0,9) B[j]=(B[j]+A[k]*g[l-1][k][j])%mo;
mset(C,0);
fo(j,0,9)
fo(k,0,9) C[j]=(C[j]+B[k]*f[r][k][j])%mo;
ll ans=0;
fo(i,0,8) ans+=C[i];
printf("%lld\n",ans%mo);
}
return 0;
}