• [bzoj1009] [HNOI2008]GT考试


    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
    

    Solution

    考虑(dp),设(f[i][j])表示做到第(i)位,不吉利数字已经匹配了(j)位了的方案数。

    那么,可以考虑从(f[i-1])转移到(f[i]),设当前位填的是(x),那么显然可以用(kmp)处理出现在匹配了多少位了,设匹配了(k)位,那么这种情况的转移方程就可以写成:

    [f[i][k]+=f[i-1][j] ]

    然后可以发现每一位的转移都是一样的,那么可以暴力处理出一次转移的参数,然后矩阵快速幂转移就好了。

    具体可以看代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    #define write(x) printf("%d
    ",x)
    
    const int maxn = 2e5+10;
    
    int mod;
    
    struct matrix {
    	int a[22][22],n,m;
    	matrix () {memset(a,0,sizeof a);n=m=0;} 
    	matrix operator * (const matrix &rhs) const {
    		matrix res;res.n=n,res.m=rhs.m;
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=rhs.m;j++) 
    				for(int k=1;k<=m;k++) 
    					(res.a[i][j]+=a[i][k]*rhs.a[k][j]%mod)%=mod;
    		return res;	
    	}
    };
    
    matrix qpow(matrix a,int x) {
    	matrix res;res.n=res.m=a.n;
    	for(int i=1;i<=a.n;i++) res.a[i][i]=1;
    	for(;x;x>>=1,a=a*a) if(x&1) res=res*a;
    	return res;	
    }
    
    char s[maxn];
    int n,m,nxt[maxn];
    
    int main() {
    	read(n),read(m),read(mod);scanf("%s",s+1);
    	for(int i=2,j=0;i<=m;i++) {
    		while(j&&s[j+1]!=s[i]) j=nxt[j];
    		if(s[j+1]==s[i]) j++;nxt[i]=j;
    	}
    	matrix tmp;tmp.n=tmp.m=m;
    	for(int i=1;i<=m;i++) 
    		for(int j=0;j<=9;j++) {
    			int p=i-1;
    			while(p&&s[p+1]-'0'!=j) p=nxt[p];
    			if(s[p+1]-'0'==j) p++;
    			if(p!=m) (++tmp.a[i][p+1])%=mod;
    		}
    	tmp=qpow(tmp,n);
    	matrix a;a.n=1,a.m=m;a.a[1][1]=1;
    	a=a*tmp;int ans=0; 
    	for(int i=1;i<=m;i++) ans=(ans+a.a[1][i])%mod;
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    linux下socket编程-TCP
    python正则表达式练习篇2
    python正则表达式练习篇
    python正则表达式基础篇
    Jmeter应用初步介绍
    数据库清除重复数据
    Nginx 获取真实 IP 方案
    Mac 实用工具bash-comletion介绍安装
    MySQL的binlog数据如何查看
    Mybatlis SQL 注入与防范
  • 原文地址:https://www.cnblogs.com/hbyer/p/10351119.html
Copyright © 2020-2023  润新知