子序列
Description
Data Constraint
Solution
考虑如何求一个序列的本质不同的子序列个数,有一个简单的
DP
。
设
F
[
设
上述的状态转移方程可以视为一个矩阵,第
i
个位置的转移方程都对应一个矩阵
那么对于每个询问只需算出
Wl−1
*
Tr
即可求解。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define fo(i,j,l) for(i=j;i<=l;i++)
#define fd(i,j,l) for(i=j;i>=l;i--)
using namespace std;
typedef long long ll;
const ll N=120000,mo=1000000007,W=11;
char s[N];
int i,len,j,ak,o=0,l,p,n,q,zb,rr;
int dy[26];
ll zqz[N][W][W],nqz[N][W][W];
ll jz[W][W][W],nj[W][W][W];
ll k1[W][W],k2[W][W],k3[W][W];
void xc()
{
int i,j,l;
fo(i,1,o) fo(l,1,o){
k3[i][l]=0;
fo(j,1,o)k3[i][l]+=k1[i][j]*k2[j][l];
k3[i][l]=k3[i][l]%mo;
}
}
void tj(int pp,int w)
{
int i,l;
fo(i,1,o) fo(l,1,o) k1[i][l]=zqz[pp-1][i][l],k2[i][l]=jz[w][i][l];
xc(); fo(i,1,o) fo(l,1,o) zqz[pp][i][l]=k3[i][l];
fo(i,1,o) fo(l,1,o) k2[i][l]=nqz[pp-1][i][l],k1[i][l]=nj[w][i][l];
xc(); fo(i,1,o) fo(l,1,o) nqz[pp][i][l]=k3[i][l];
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
fo(i,1,n)
if(!dy[s[i]-'a'])dy[s[i]-'a']=++o;
o++;
fo(i,1,o-1)
fo(l,1,o)jz[i][l][l]=1,jz[i][i][l]=1;
fo(i,1,o-1) fo(l,1,o) nj[i][l][l]=1;
fo(i,1,o-1) fo(l,1,o) if(i!=l) nj[i][i][l]=mo-1;
fo(i,1,o)zqz[0][i][i]=1,nqz[0][i][i]=1;
fo(i,1,n)tj(i,dy[s[i]-'a']);
scanf("%d",&q);
fo(i,1,q)
{
scanf("%d%d",&zb,&rr);
fo(l,1,o)fo(j,1,o)k1[l][j]=nqz[zb-1][l][j],k2[l][j]=zqz[rr][l][j];
xc(); ll ans=0;
fo(l,1,o-1)ans=(ans+k3[l][o])%mo;
printf("%lld\n",ans);
}
}