BZOJ1009: [HNOI2008]GT考试

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1009

f[i][j]表示当前扫到了第i位,已经匹配了j个。(感觉很多这样匹配的问题都是这么玩的,因为不出现某段xx就是它一直在匹配,但从未成功过。

然后,我们插一位数进去变成f[i+1][],对于插进去的这位数,有可能是s[i+1],也有可能不是,那就让它按着fail边跑回去嘛。

f[i+1][k]=f[i][j]+1 。。。

然后跑一遍矩乘。。

那么答案就是∑f[0][i]。。

(明天就要考试了我还在这里浪。。看来是要出事了。。为了防止以后傻逼还是把这傻逼的题解写一写。。蒟蒻脑袋一卡壳就卡好久TAT。。

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 25
using namespace std;
int a[maxn][maxn],b[maxn][maxn],c[maxn][maxn],p[maxn],n,m,K,ans;
char s[maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void get(int a[maxn][maxn],int b[maxn][maxn],int ans[maxn][maxn]){
    rep(i,0,m-1) rep(j,0,m-1) c[i][j]=0;
    rep(i,0,m-1) rep(j,0,m-1) rep(k,0,m-1) 
        c[i][j]=(c[i][j]+a[i][k]*b[k][j])%K;
    rep(i,0,m-1) rep(j,0,m-1) ans[i][j]=c[i][j];
}
int main(){
    n=read(); m=read(); K=read();
    scanf("%s",s+1);
    int j=0;
    rep(i,2,m) {
        while (j&&s[j+1]!=s[i]) j=p[j];
        if (s[j+1]==s[i]) j++;
        p[i]=j;
    } 
    rep(i,0,m-1) rep(j,0,9){
        int t=i;
        while (t&&s[t+1]-'0'!=j) t=p[t];
        if (s[t+1]-'0'==j) t++;
        if (t!=m) b[i][t]=(b[i][t]+1)%K;  
    } 
    rep(i,0,m-1) a[i][i]=1;
    while (n){
        if (n&1) get(a,b,a);
        get(b,b,b);
        n/=2;
    }
    rep(i,0,m-1) ans=(ans+a[0][i])%K;
    printf("%d\n",ans);
    return 0;
}

 

posted on 2015-12-23 21:31  ctlchild  阅读(150)  评论(0编辑  收藏  举报

导航