码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂

时间:2015-05-12 23:05:18      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:


经典题目了....虽然只有一个不能出现的字符串,但还是写了ac自动机

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 2051  Solved: 1257
[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位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6

Output

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

Sample Input

4 3 100
111

Sample Output

81

HINT

Source

[Submit][Status][Discuss]


/* ***********************************************
Author        :CKboss
Created Time  :2015年05月12日 星期二 08时16分03秒
File Name     :BZOJ1009.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;
const int maxn=1200;

int idx(char c) { return c-'0'; }

int ch[maxn][11],fail[maxn],end[maxn];
int root,sz;
char str[maxn];

int newnode()
{
	memset(ch[sz],-1,sizeof(ch[sz]));
	end[sz++]=0;
	return sz-1;
}

void ac_init() { sz=0; root=newnode(); }

void ac_insert(char str[])
{
	int len=strlen(str);
	int now=root;
	for(int i=0;i<len;i++)
	{
		int id=idx(str[i]);
		if(ch[now][id]==-1) ch[now][id]=newnode();
		now=ch[now][id];
	}
	end[now]++;
}

void ac_build()
{
	queue<int> q;
	fail[root]=root;
	for(int i=0;i<10;i++)
	{
		if(ch[root][i]==-1)
			ch[root][i]=root;
		else
		{
			fail[ch[root][i]]=root;
			q.push(ch[root][i]);
		}
	}
	while(!q.empty())
	{
		int now=q.front(); q.pop();
		end[now]+=end[fail[now]];
		for(int i=0;i<10;i++)
		{
			if(ch[now][i]==-1)
				ch[now][i]=ch[fail[now]][i];
			else
			{
				fail[ch[now][i]]=ch[fail[now]][i];
				q.push(ch[now][i]);
			}
		}
	}
}

int n,m,mod;

typedef vector<int> vi;

struct MATRIX
{
	int _x,_y;
	int matrix[30][30];

	MATRIX(){};
	MATRIX(int n)
	{
		_x=_y=n;
		memset(matrix,0,sizeof(matrix));
	}

	void getOne(int n)
	{
		for(int i=0;i<n;i++)
			matrix[i][i]=1;
	}

	MATRIX operator* (const MATRIX& b) const
	{
		int n=b._x;
		MATRIX ret(n);
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				int temp=0;
				for(int k=0;k<n;k++)
				{
					temp=(temp+matrix[i][k]*b.matrix[k][j])%mod;
				}
				ret.matrix[i][j]=temp%mod;
			}
		}
		return ret;
	}
};

MATRIX QuickPow(MATRIX M,int n)
{
	MATRIX ans;
	ans.getOne(M._x);
	while(n)
	{
		if(n&1) ans=ans*M;
		M=M*M;
		n/=2;
	}
	return ans;
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	scanf("%d%d%d",&n,&m,&mod);
	scanf("%s",str);

	ac_init();
	ac_insert(str);
	ac_build();

	MATRIX mat(sz);

	for(int i=0;i<sz;i++)
	{
		if(end[i]) continue;
		for(int j=0;j<10;j++)
		{
			int p=ch[i][j];
			if(end[p]||end[fail[p]]) continue;
			mat.matrix[i][p]++;
		}
	}

	MATRIX ret=QuickPow(mat,n);

	int ans=0;

	for(int i=0;i<sz;i++)
	{
		ans=(ans+ret.matrix[0][i])%mod;
	}

	printf("%d\n",ans);
    
    return 0;
}


BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂

标签:

原文地址:http://blog.csdn.net/ck_boss/article/details/45675237

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!