如果只考虑求一个数列的不同子序列个数,可以简单地DP出来
fi=2×fi−1−flstai−1 ,其中 lstj 表示字符 j 上次出现的位置,没出现过就忽略
但是这样不好维护
可以换一种DP方式, fi,j 表示以字符 i 开头,字符 j 结尾的子序列个数。
那么在左边新加一个字符 x , fx,i 会加上 ∑j≠xfj,i ,考虑以 x 开头的子序列,去掉开头的所有连续的 x 后的子序列个数就是 ∑j≠xfj,i ,然后这些子序列在开头加一些 x 是原本的 fx,i ,在加上当前的 x 就都是未出现过的了…
这话说的我自己都看不懂
大概就这样可以用莫队维护
然后就被卡常了……
学了一下wxh的莫队打法
friend bool operator <(const QQ &a,const QQ &b){
return pos[a.l].l] || (pos[a.l]==pos[b.l] && (pos[a.l]&1 ? a.r.r : a.r>b.r));
}
然后就过了…
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=100010,P=1e9+7;
int n,q,S;
ll b[15][15];
int a[N];
int ans[N];
int pos[N];
struct QQ{
int l,r,g;
friend bool operator <(const QQ &a,const QQ &b){
return pos[a.l]1?a.rb.r));
}
}Q[N];
ll cur;
inline void add(ll &x,ll y){
(x+=y)%=P;
}
inline void Addr(const int &x){
for(int i=1;i<=9;i++){
int now=(b[i][0]-b[i][x]+(i==x));
cur+=now; add(b[i][x],now); add(b[0][x],now); add(b[i][0],now);
}
cur%=P;
}
inline void Addl(const int &x){
for(int i=1;i<=9;i++){
int now=(b[0][i]-b[x][i]+(i==x));
cur+=now; add(b[x][i],now); add(b[x][0],now); add(b[0][i],now);
}
cur%=P;
}
inline void Minusl(const int &x){
for(int i=1;i<=9;i++){
int now=-(b[0][i]-b[x][i]+(i==x));
cur+=now; add(b[x][i],now); add(b[x][0],now); add(b[0][i],now);
}
cur%=P;
}
inline void Minusr(const int &x){
for(int i=1;i<=9;i++){
int now=-(b[i][0]-b[i][x]+(i==x));
cur+=now; add(b[i][x],now); add(b[0][x],now); add(b[i][0],now);
}
cur%=P;
}
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rea(int *a){
char c=nc(); int len=0;
for(;c>'z'||c<'a';c=nc());for(;c>='a'&&c<='z';a[++len]=c-'a'+1,c=nc()); return len;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
int main(){
S=sqrt(n=rea(a));
rea(q);
for(int i=1;i<=n;i++) pos[i]=i/S;
for(int i=1;i<=q;i++)
rea(Q[i].l),rea(Q[i].r),Q[i].g=i;
sort(Q+1,Q+1+q);
int l=1,r=0;
for(int i=1;i<=q;i++){
while(rwhile(r>Q[i].r) Minusr(a[r--]);
while(lwhile(l>Q[i].l) Addl(a[--l]);
ans[Q[i].g]=(cur+P)%P;
}
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
return 0;
}