【JZOJ 5132】 子序列

来源:互联网 发布:雷神笔记本怎么样知乎 编辑:程序博客网 时间:2024/06/11 16:36

Description

这里写图片描述
这里写图片描述

40%

dp,很简单所以不说了

100%

小写字母只有前9个,考虑抓住这个突破口
仔细观察dp式子
f[i][s[i]]=1+chf[i1][ch]
f[i][ch]=f[i1][ch]
这可以写成矩阵的形式,我们可以预处理出矩阵前缀积,逆矩阵前缀积
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;}
原创粉丝点击