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; }