zoukankan      html  css  js  c++  java
  • 【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)

    【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)

    题面

    BZOJ

    题解

    看到这个题目
    化简一下题意
    长度为(n)的,由(0~9)组成的字符串中
    不含串(s)的串的数量有几个

    很显然,如果组成的字符串和(s)串做(KMP)的匹配的话
    是不能匹配到最后一位的

    所以,我们想到一个很显然的方程
    (f[i][j])表示当前做了第(i)位,在(s)串中匹配到了第(j)
    每次枚举下一位放的数字
    以及每一位的位置
    相当于做(KMP)的匹配
    然后进行转移

    所以,我们可以写出一个暴力

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int f[2000][30];
    int nt[30],n,m,K;
    char s[30];
    void Get_Next(char *s)
    {
    	int l=strlen(s+1);
    	nt[1]=0;
    	for(int i=2;i<=l;++i)
    	{
    		int t=nt[i-1];
    		while(t&&s[i]!=s[t+1])t=nt[t];
    		if(s[i]==s[t+1])t+=1;
    		nt[i]=t;
    	}
    }
    int main()
    {
    	n=read();m=read();K=read();
    	scanf("%s",s+1);
    	Get_Next(s);
    	f[0][0]=1;
    	for(int i=0;i<n;++i)
    	{
    		for(int j='0';j<='9';++j)
    		{
    			for(int k=0;k<m;++k)
    			{
    				int t=k;
    				while(t&&s[t+1]!=j)t=nt[t];
    				if(j==s[t+1])t++;
    				(f[i+1][t]+=f[i][k])%=K;
    			}
    		}
    	}
    	int ans=0;
    	for(int i=0;i<m;++i)ans+=f[n][i];
    	printf("%d
    ",ans%K);
    	return 0;
    }
    
    

    (n)的范围有(10^9)
    不可能是(O(n))解了
    我们发现每次匹配的转移关系是一定的
    所以可以用矩阵快速幂来优化(dp)转移

    复杂度为(O(n+m^3logn))

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int nt[30],n,m,K;
    char s[30];
    void Get_Next(char *s)
    {
    	int l=strlen(s+1);
    	nt[1]=0;
    	for(int i=2;i<=l;++i)
    	{
    		int t=nt[i-1];
    		while(t&&s[i]!=s[t+1])t=nt[t];
    		if(s[i]==s[t+1])t+=1;
    		nt[i]=t;
    	}
    }
    struct Dalao
    {
    	int s[30][30];
    	void init()
    		{
    			memset(s,0,sizeof(s));
    			for(int i=0;i<m;++i)s[i][i]=1;
    		}
    	void clear(){memset(s,0,sizeof(s));}
    }G;
    Dalao operator*(Dalao a,Dalao b)
    {
    	Dalao ret;ret.clear();
    	for(int i=0;i<m;++i)
    		for(int j=0;j<m;++j)
    			for(int k=0;k<m;++k)
    				(ret.s[i][j]+=a.s[i][k]*b.s[k][j]%K)%=K;
    	return ret;
    }
    Dalao fpow(Dalao a,int b)
    {
    	Dalao s;s.init();
    	while(b){if(b&1)s=s*a;a=a*a;b>>=1;}
    	return s;
    }
    int main()
    {
    	n=read();m=read();K=read();
    	scanf("%s",s+1);
    	Get_Next(s);
    	for(int j='0';j<='9';++j)
    	{
    		for(int k=0;k<m;++k)
    		{
    			int t=k;
    			while(t&&s[t+1]!=j)t=nt[t];
    			if(j==s[t+1])t++;
    			G.s[k][t]++;
    		}
    	}
    	G=fpow(G,n);
    	int ans=0;
    	for(int i=0;i<m;++i)ans=(ans+G.s[0][i])%K;
    	printf("%d
    ",ans%K);
    	return 0;
    }
    
    
  • 相关阅读:
    spark 读取mongodb失败,报executor time out 和GC overhead limit exceeded 异常
    在zepplin 使用spark sql 查询mongodb的数据
    Unable to query from Mongodb from Zeppelin using spark
    spark 与zepplin 版本兼容
    kafka 新旧消费者的区别
    kafka 新生产者发送消息流程
    spark ui acl 不生效的问题分析
    python中if __name__ == '__main__': 的解析
    深入C++的new
    NSSplitView
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8310580.html
Copyright © 2011-2022 走看看