BZOJ1009: [HNOI2008]GT考试

2 篇文章 0 订阅
1 篇文章 0 订阅

BZOJ1009: [HNOI2008]GT考试

Dp·KMP·矩阵优化

题解:

不想自己写题解系列。

http://blog.csdn.net/loi_dqs/article/details/50897662

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
typedef long long ll;
const ll N = 25;

ll n,m,mod,fail[N]; char s[N];

struct Matrix{
    ll d[N][N]; ll x,y;
    Matrix(ll _x,ll _y,ll op=0){
        x=_x; y=_y;
        for(ll i=0;i<x;i++) for(ll j=0;j<y;j++)
            if(i==j) d[i][j]=op; else d[i][j]=0;
    }
    ll* operator [] (ll x){ return d[x]; }
    void debug(){
//      puts("debug:");
//      D(x); D(y); E;
//      for(ll i=0;i<x;i++) for(ll j=0;j<y;j++) 
//          printf("%lld%c",d[i][j],j==y-1?'\n':' ');
    }
};

Matrix operator * (Matrix &a, Matrix &b){
    Matrix c(a.x,b.y);
    for(ll i=0;i<a.x;i++) for(ll j=0;j<a.y;j++) for(ll k=0;k<b.y;k++)
        c[i][k]=(c[i][k]+a[i][j]*b[j][k]%mod)%mod;
    return c;
}

Matrix pow(Matrix a,ll k){
    Matrix res(a.x,a.y,1);
    while(k){
        if(k&1) res=res*a;
        a=a*a; k>>=1;
    }
    return res;
}

void getfail(Matrix &a){
    fail[0]=0; fail[1]=0;
    for(ll i=1;i<m;i++){
        ll j=fail[i];
        while(j && s[i]!=s[j]) j=fail[j];
        fail[i+1]= s[i]==s[j] ? j+1 : 0; 
    }
    for(ll i=0;i<m;i++){
        for(ll j=0;j<=9;j++){
            ll p=i;
            while(p && s[p]!=j+'0') p=fail[p];
            if(s[p]==j+'0') p++;
            if(p<m) a[i][p]++;
        }
    }
}

int main(){
    freopen("a.in","r",stdin);
    scanf("%lld%lld%lld%s",&n,&m,&mod,s);
    Matrix a(m,m); getfail(a); a.debug();
    a=pow(a,n); a.debug();
    Matrix f(1,m); f[0][0]=1; 
    f=f*a; f.debug();
    ll ans=0;
    for(ll i=0;i<m;i++) ans=(ans+f[0][i])%mod;
    printf("%lld\n",ans); 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值