[ DP KMP 矩乘优化 ] Codeforces946F Fibonacci String Subsequences

3 篇文章 0 订阅
2 篇文章 0 订阅

先对原串做一次KMP。
先考虑朴素的DP:
fi,j f i , j 表示 F(x) F ( x ) 的前 i i 个字符能匹配到 s 串第 j j 位的方案数,结合KMP就可以转移了。
把状态用矩阵表示,对每个 F(i) 求出答案矩阵和转移矩阵,就可以递推求出答案了。

#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=1000000007;
int k,n,m,Res;
int F[N];
char s[N];
inline void Add(int& x,int y){
    x=(x+y)%M;
}
struct Matrix{
    int a[N][N];
    Matrix operator * (Matrix b)const{
        Matrix c;
        memset(c.a,0,sizeof(c.a));
        for(int k=0;k<=n;k++)
            for(int i=0;i<=n;i++)
                if(a[i][k])
                    for(int j=0;j<=n;j++)
                        if(b.a[k][j])Add(c.a[i][j],1ll*a[i][k]*b.a[k][j]%M);
        return c;
    }
}f[N],Ans[N],t;
inline void Build(){
    for(int i=1;i<n;i++){
        int j=F[i];
        while(j&&s[j]!=s[i])j=F[j];
        F[i+1]=s[i]==s[j]?j+1:0;
    }
}
inline int Get(int x,int y){
    while(x&&s[x]!=y+'0')x=F[x];
    return s[x]==y+'0'?x+1:0;
}
int main(){
    scanf("%d%d",&n,&m);
    scanf("%s",s);
    Build();
    for(int i=0;i<n;i++)
        for(int j=0;j<2;j++){
            int t=Get(i,j);
            if(t==n)Add(f[j].a[i][F[n]],1);
            Add(f[j].a[i][t],1);Add(f[j].a[i][i],1);
        }
    f[0].a[n][n]=f[1].a[n][n]=2;
    t.a[0][0]=1;Ans[0]=t*f[0];Ans[1]=t*f[1];
    for(int i=2;i<=m;i++)f[i]=f[i-1]*f[i-2],Ans[i]=Ans[i-1]*f[i-2];
    cout<<Ans[m].a[0][n]<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值