• [HNOI2008]GT考试


    很容易想到暴力的转移:f[i][j]表示较长串的前i个字母,最后和不吉利数字相同的已经有j个。价格数组g[j][k]表示第j个不吉利前缀转移到不吉利前缀k的方案数。然后kmp一下就能求得g数组。看到n是1e9,矩阵快速幂优化即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int n,m,mod,nxt[25];
    char s[25];
    struct Matrix {
    	int g[25][25],n,m;
    	Matrix () {memset(g,0,sizeof g);n=m=0;}
    	Matrix operator * (const Matrix &b) const {
    		Matrix ans;ans.n=n,ans.m=b.m;
    		for(int i=0;i<=ans.n;i++)
    		for(int k=0;k<=m;k++)
    		for(int j=0;j<=ans.m;j++)
    		ans.g[i][j]=(ans.g[i][j]+g[i][k]*b.g[k][j])%mod;
    		return ans;
    	}
    }A,B;
    Matrix ksm(Matrix a,int z) {
    	Matrix res=a;
    	z--;
    	while(z) {
    		if(z&1) res=res*a;
    		a=a*a;
    		z>>=1;
    	}
    	return res;
    }
    int main() {
    	scanf("%d%d%d",&m,&n,&mod);
    	scanf("%s",s);
    	for(int i=1,j=0;i<n;i++) {
    		while((s[i]!=s[j])&&j) j=nxt[j];
    		if(s[i]==s[j]) j++;
    		nxt[i+1]=j;
    	}
    	for(int i=0,j;i<n;i++)
    		for(int k=0;k<10;k++)	{
    			j=i;while(j&&s[j]!=k+'0') j=nxt[j];
    			if(s[j]==k+'0') j++;
    			A.g[i][j]++;
    	}
    	A.m=A.n=B.m=n-1;
    	B.n=0;B.g[0][0]=1;
    	Matrix ans=B*ksm(A,m);
    	int cnt=0;
    	for(int i=0;i<n;i++) cnt=(cnt+ans.g[0][i])%mod;
    	printf("%d",cnt);
    }
    
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    字符串与Json操作
    默认让IE用最高文档模式浏览网页
    MVC中简单的文件下载代码
    2017年1月22日
    JDK环境变量设置
    如何实现windows命令提示符的tab补全
    win7热点设置
    为什么小米5不能适配win7
    各种错误锦集
    插头DP
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9386794.html
Copyright © 2020-2023  润新知