博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj1009 [HNOI2008]GT考试(AC+矩乘优化dp)
阅读量:5025 次
发布时间:2019-06-12

本文共 2191 字,大约阅读时间需要 7 分钟。

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

分析:

第一眼:这难道不是一道数位dp吗
f[i][j][k][0/1][0/1][0/1][0/1]
第i位,添的数字是j,和模式串的第k位相不相同[0/1],模式串的1~k-1位是不是都匹配上了,1~i位中有没有模式串,卡不卡上界

一看数据范围,数位dp就等着吔shi吧。。。

所以这又是一道dp
暴力dp的话,和一样

在构建AC自动机的时候,

有一个语句是普通的AC自动机不具有的

for (i=0;i<=9;i++)    if (!ch[0][i]) ch[0][i]=++tot;

这样在之后是有用的

N的范围使我们不得不考虑优化,因为只有一个字符串

每个状态都是由固定的几个转移而来的,这就让我们想到了矩阵优化

那我们就要来构造矩阵了

首先明确状态转移方程:
f[i][j] 表示匹配到i位置,在AC自动机上的j节点
f[i][j]向i+1转移,枚举0~9,如果下一个节点不是ed节点
那么我们就可以继续转移

现在我们就要构造一个tot(AC自动机上的节点数量)*tot的矩阵

H[当前点][可以转移点]=1
这时AC自动机中看似多余的语句,就起了作用了:
任何不存在于M中的数字都可以看作是根节点
这里写图片描述

说实话,f[1]的初始化我是看不大懂的

最后的答案实际上就是在H矩阵自乘完之后,再乘上一个f[1]
把值都加起来

for (int i=1;i<=tot;i++){    t[i]=0;    for (int j=1;j<=tot;j++)        t[i]=(t[i]+f[1][j]*ans.H[j][i]%p)%p;    sum=(sum+t[i])%p;}

这里写图片描述

tip

在KSM的时候,只用自乘n-1次,因为f[1]我们已经处理出来了

所有需要循环AC自动机节点的地方,都是从1开始

除了在处理f[1]的时候:
这里写图片描述

//这里写代码片#include
#include
#include
#define ll long longchar s[30];int q[1010],tou,wei,fail[1010],ch[300][30],tot=0,f[2][1001];bool ed[1010];int p,n,m,k;struct node{ int H[100][100]; node operator *(const node &a)const { node ans; for (int i=1;i<=tot;i++) for (int j=1;j<=tot;j++) { ans.H[i][j]=0; for (int k=1;k<=tot;k++) ans.H[i][j]=(ans.H[i][j]+H[i][k]*a.H[k][j]%p)%p; } return ans; } void print(node ans) { for (int i=1;i<=tot;i++) { for (int j=1;j<=tot;j++) printf("%d ",ans.H[i][j]); printf("\n"); } } void clear() { memset(H,0,sizeof(H)); } node KSM(int pp) { node a=(*this),an=(*this); pp--; while (pp) { if (pp&1) an=an*a; a=a*a; pp>>=1; } return an; }};node H,ans;void insert(){ int i,now=0; for (i=0;i

转载于:https://www.cnblogs.com/wutongtong3117/p/7673128.html

你可能感兴趣的文章
二叉树的遍历问题总结
查看>>
3.14-3.20周总结
查看>>
Spring之面向切面编程AOP
查看>>
MATLAB GUI程序设计中使文本框接收多行输入的方法
查看>>
全文检索-Elasticsearch (四) elasticsearch.net 客户端
查看>>
Oracle DBMS_SESSION
查看>>
sublime复制当前行到下一行
查看>>
WPF 3D变换应用
查看>>
luogu4012 深海机器人问题 网络流
查看>>
android 拍照上传照片
查看>>
ArchLinux安装开源VMware Tools
查看>>
系统用户分析模型
查看>>
DB2 锁升级示例1
查看>>
16.RDD实战
查看>>
MainFrame知识小结(20120210)—dfsort/syncsort中的数据类型
查看>>
jsp题库 (一)小测(25/21)
查看>>
D - Flip tile
查看>>
Java连接RabbitMQ之创建连接
查看>>
开户vim编程之--cscope支持
查看>>
python数据类型图解
查看>>