zoukankan      html  css  js  c++  java
  • [HNOI2008]GT考试

    题目

    洛谷
    BZOJ

    做法

    朴素做法:

    设数组(dp[i][j])为前(i)位后缀(j)位恰好(避免特判)对应禁止字符前缀(j)

    (dp[i][j]=sumlimits_{c=0}^m k[c] dp[i-1][c]),由于是恰好对应,系数(k)(KMP)随便搞搞就出来了

    数位dp差不多

    丢到矩阵里快速幂

    My complete code

    #include<bits/stdc++.h>
    using namespace std;
    typedef int LL;
    const LL maxn=31;
    LL n,m,p,ans;
    LL nxt[maxn],a[maxn][maxn];
    char s[maxn];
    struct Mat{
    	LL v[maxn][maxn];
    	inline void Init(LL x=0){
    		memset(v,0,sizeof(v));
    		for(LL i=0;i<m;++i) v[i][i]=x;
    	}
    }M;
    inline Mat Mul(const Mat &a,const Mat &b){
    	Mat c; c.Init();
    	for(LL i=0;i<m;++i)
    	    for(LL j=0;j<m;++j)
    	        for(LL k=0;k<m;++k)
    	            c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%p;
    	return c;
    }
    inline Mat Fpow(Mat base,LL b){
    	Mat ret; ret.Init(1);
    	while(b){
    		if(b&1) ret=Mul(ret,base);
    		base=Mul(base,base),b>>=1;
    	}return ret;
    }
    int main(){
    	scanf("%d%d%d %s",&n,&m,&p,s);
    	
    	LL len(strlen(s)),k(0);
    	for(LL i=1;i<m;++i){
    		while(k && s[k]!=s[i])
    		    k=nxt[k-1];
    		if(s[k]==s[i]) ++k;
    		nxt[i]=k;
    	}
    	a[0][s[0]-'0']=1;
    	for(LL i=1;i<m;++i)
    	    for(LL ch=0;ch<=9;++ch){
    	    	LL k(i);
    	    	char c(ch+'0');
    	    	while(k && s[k]!=c)
    	    	    k=nxt[k-1];
    	    	if(s[k]==c) ++k;
    	    	a[i][ch]=k;
    		}
    	M.Init();
    	for(LL i=0;i<m;++i)
    	    for(LL ch=0;ch<=9;++ch)
    	        ++M.v[i][a[i][ch]];
    	M=Fpow(M,n);
    	for(LL i=0;i<m;++i)
    	    ans=(ans+M.v[0][i])%p;
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    性能优化
    几种跨域处理
    重温前端基础之-数组去重
    移动端常遇到的问题
    WPF 应用
    WPF 应用
    WPF 应用
    C# 应用
    WPF 应用
    C# 应用
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10369849.html
Copyright © 2011-2022 走看看