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

    1009: [HNOI2008]GT考试

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 3434  Solved: 2109
    [Submit][Status][Discuss]

    Description

      阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
    他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为
    0

    Input

      第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000

    Output

      阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.

    Sample Input

    4 3 100
    111

    Sample Output

    81

    HINT

     

    Source

    分析:

     我们可以想到这题可以用$DP$来完成,$f[i][j]$代表构造方案的第$i$个字符匹配上了不吉利数字的第$j$个字符的合法方案数,然后我们枚举下一位填哪个数字转移到哪里,如果我们枚举的数字$k$恰好匹配上了第$j+1$个不吉利数字,那么就可以转移到$f[i+1][j+1]$,否则我们就通过$kmp$来找到转移的状态...

    发现不吉利数字的长度很小,方案数字的长度很大,所以可以用矩阵快速幂来优化转移...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=20+5;
    
    int n,m,mod,nxt[maxn];
    
    char s[maxn];
    
    struct Matrix{
    	
    	int a[maxn][maxn];
    	
    	inline void clear(void){
    		memset(a,0,sizeof(a));
    	}
    	
    	friend Matrix operator * (Matrix x,Matrix y){
    		Matrix ans;ans.clear();
    		for(int i=0;i<n;i++)
    			for(int j=0;j<n;j++)
    				for(int k=0;k<n;k++)
    					(ans.a[i][j]+=(x.a[i][k]*y.a[k][j])%mod)%=mod;
    		return ans;
    	}
    	
    	inline Matrix power(Matrix M,int x){
    		Matrix ans;ans.clear();
    		for(int i=0;i<n;i++)
    			ans.a[i][i]=1;
    		while(x){
    			if(x&1)
    				ans=ans*M;
    			M=M*M,x>>=1;
    		}
    		return ans;
    	}
    	
    }G;
    
    inline void getnxt(void){
    	nxt[0]=nxt[1]=0;int k;
    	for(int i=1;i<n;i++){
    		k=nxt[i];
    		while(k&&s[i+1]!=s[k+1])
    			k=nxt[k];
    		if(s[i+1]==s[k+1])
    			nxt[i+1]=k+1;
    		else
    			nxt[i+1]=0;
    	}
    }
    
    inline void getmatrix(void){
    	for(int i=0;i<n;i++)
    		for(int j=0,k;j<=9;j++){
    			k=i;
    			while(k&&(int)(s[k+1]-'0')!=j)
    				k=nxt[k];
    			if((int)(s[k+1]-'0')==j)
    				k++;
    			else
    				k=0;
    			G.a[i][k]++;
    		}
    }
    
    inline int solve(void){
    	G=G.power(G,m);
    	int ans=0;
    	for(int i=0;i<=n;i++)
    		(ans+=G.a[0][i])%=mod;
    	return ans;
    }
    
    signed main(void){
    	scanf("%d%d%d%s",&m,&n,&mod,s+1);G.clear();
    	getnxt();getmatrix();printf("%d
    ",solve());
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    Win10 UWP Tile Generator
    Win10 BackgroundTask
    UWP Tiles
    UWP Ad
    Win10 build package error collections
    Win10 八步打通 Nuget 发布打包
    Win10 UI入门 pivot multiable DataTemplate
    Win10 UI入门 导航滑动条 求UWP工作
    UWP Control Toolkit Collections 求UWP工作
    Win10 UI入门 SliderRectangle
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6409792.html
Copyright © 2011-2022 走看看