[BZOJ1009][HNOI2008]GT考试(AC自动机+dp+矩阵优化)
来源:互联网 发布:sql团体培训 编辑:程序博客网 时间:2024/06/05 05:47
题目描述
传送门
题解
40%的数据和BZOJ1030文本生成器是一样的:f[i][j]表示准考证上第i位数和trie树上编号为j的节点匹配,不出现不吉利数字的方案数.
考虑矩阵优化。目标矩阵表示了f中一维的状态。如果点i可以转移到ch[i][k],那么在转移矩阵的第i行第ch[i][k]列置1.判断是否成立的方法还是fail树。
代码
暴力dp
#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int max_n=1005;const int max_m=105;int n,m,Mod,ans,tot;char s[max_n];int f[max_n][max_m];int ch[max_m][20],fail[max_m];bool is_end[max_m];queue <int> q;inline void insert(){ int now=0; for (int i=0;i<m;++i) { int x=s[i]-'0'; if (!ch[now][x]) ch[now][x]=++tot; now=ch[now][x]; } is_end[now]=true;}inline void make_fail(){ while (!q.empty()) q.pop(); for (int i=0;i<=9;++i) if (ch[0][i]) q.push(ch[0][i]); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=0;i<=9;++i) { if (!ch[now][i]) { ch[now][i]=ch[fail[now]][i]; continue; } int x=ch[now][i]; fail[x]=ch[fail[now]][i]; if (is_end[fail[x]]) is_end[x]=true; q.push(x); } }}int main(){ scanf("%d%d%d\n",&n,&m,&Mod); gets(s); insert(); for (int i=0;i<=9;++i) if (!ch[0][i]) ch[0][i]=++tot; make_fail(); f[0][0]=1; for (int i=1;i<=n;++i) for (int j=0;j<=tot;++j) { if (is_end[j]||is_end[fail[j]]) continue; for (int k=0;k<=9;++k) f[i][ch[j][k]]=(f[i][ch[j][k]]+f[i-1][j])%Mod; } for (int i=0;i<=tot;++i) printf("%d%c",f[1][i]," \n"[i==tot]); for (int i=0;i<=tot;++i) if (!is_end[i]) ans=(ans+f[n][i])%Mod; printf("%d\n",ans);}
矩阵优化
#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int max_n=1005;const int max_m=105;int n,m,Mod,final,tot;char s[max_n];int ch[max_m][20],fail[max_m];bool is_end[max_m];struct hp{int a[max_m][max_m];}unit,A,f,ans;queue <int> q;inline void insert(){ int now=0; for (int i=0;i<m;++i) { int x=s[i]-'0'; if (!ch[now][x]) ch[now][x]=++tot; now=ch[now][x]; } is_end[now]=true;}inline void make_fail(){ while (!q.empty()) q.pop(); for (int i=0;i<=9;++i) if (ch[0][i]) q.push(ch[0][i]); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=0;i<=9;++i) { if (!ch[now][i]) { ch[now][i]=ch[fail[now]][i]; continue; } int x=ch[now][i]; fail[x]=ch[fail[now]][i]; if (is_end[fail[x]]) is_end[x]=true; q.push(x); } }}inline hp cheng(hp a,hp b){ hp ans; memset(ans.a,0,sizeof(ans.a)); for (int i=0;i<=tot;++i) for (int j=0;j<=tot;++j) for (int k=0;k<=tot;++k) ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]%Mod)%Mod; return ans;}inline hp matrix_fast_pow(hp a,int p){ hp ans=unit; for (;p;p>>=1,a=cheng(a,a)) if (p&1) ans=cheng(ans,a); return ans;}int main(){ scanf("%d%d%d\n",&n,&m,&Mod); gets(s); insert(); for (int i=0;i<=9;++i) if (!ch[0][i]) ch[0][i]=++tot; make_fail(); for (int i=0;i<=tot;++i) if (!is_end[i]&&!is_end[fail[i]]) for (int k=0;k<=9;++k) A.a[i][ch[i][k]]=1; for (int i=0;i<=tot;++i) if (!is_end[i]&&!is_end[fail[i]]) for (int k=0;k<=9;++k) if (i==0) f.a[0][ch[i][k]]++; for (int i=0;i<=tot;++i) unit.a[i][i]=1; ans=matrix_fast_pow(A,n-1); ans=cheng(f,ans); for (int i=0;i<=tot;++i) if (!is_end[i]) final=(final+ans.a[0][i])%Mod; printf("%d\n",final);}
总结
之前写过的dp多复习复习吧,AC自动机好弱要多做做了。
0 0
- [BZOJ1009][HNOI2008]GT考试(AC自动机+dp+矩阵优化)
- bzoj1009 [HNOI2008]GT考试(AC+矩乘优化dp)
- bzoj1009 GT考试(AC自动机+DP+矩阵快速幂)
- 【BZOJ1009】GT考试(HNOI2008)-DP矩阵优化+KMP
- 【BZOJ1009】【HNOI2008】GT考试 AC自动机+矩阵乘法
- 【DP+矩阵优化】[HNOI2008][HYSBZ/BZOJ1009]GT考试
- 【KMP+DP+矩阵优化】BZOJ1009 [HNOI2008]GT考试
- BZOJ1009: [HNOI2008]GT考试(KMP+矩阵优化DP)
- bzoj 1009: [HNOI2008]GT考试(AC自动机+矩阵优化dp)
- 【bzoj1009】[HNOI2008]GT考试 矩阵+kmp+DP
- BZOJ1009 [HNOI2008]GT考试(KMP算法+矩阵加速dp)
- bzoj1009 [HNOI2008]GT考试(KMP+DP+矩阵倍增)
- [bzoj1009][HNOI2008]GT考试(dp+矩阵加速+KMP)
- BZOJ1009 [HNOI2008]GT考试 矩阵
- bzoj1009 GT考试 KMP+矩阵优化DP
- [BZOJ]1009 [HNOI2008]GT考试(ac自动机+矩阵快速幂优化状态转移)
- BZOJ1009 [HNOI2008]GT考试【kmp+矩阵加速DP】
- 【DP+KMP+矩阵乘法】BZOJ1009(HNOI2008)[GT考试]题解
- 勾股定理每日一证 2
- Stream对数字处理
- LeetCode 351. Android Unlock Patterns(安卓解锁)
- 【设计模式】创建型模式之生成器Builder
- JavaScript概览(一)--基本语法
- [BZOJ1009][HNOI2008]GT考试(AC自动机+dp+矩阵优化)
- linux 学习笔记(三):open、creat、close 函数的使用,文件的创建、打开与关闭
- Karatsuba algorithm C++ implementation
- Laravel 完整开源项目大全
- linux 系统
- vector::erase方法,返回值是更新后的容器的被删除元素的后一个元素的迭代器,如果需要指向删除元素的前面一个元素的迭代器就要-1
- 大整数乘法
- CSS选择器
- memento