[BZOJ 3530][Sdoi 2014]数数
2014-11-17 20:58
387 查看
阿拉~好像最近总是做到 AC 自动机的题目呢喵~
题目的算法似乎马上就能猜到的样子…… AC 自动机 + 数位 dp
先暴力转移出 f[i][j] :表示从 AC 自动机上第 j 号节点走 i 步且不碰到匹配串的方案数
然后直接用数位 dp 一位一位的试就可以了,大家都会吧~
但是…… 有前导 0 的情况真尼玛蛋疼啊!
忽的灵光一闪……
前导 0 仅能影响长度小于 L 的数的统计
那么所有长度 <L 的数全部专门暴力统计一边不就可以了!我真是特么太机智了喵~ O(∩_∩)O~
虽然有个 O(10*L*l) 的转移 但是只跑了 272 ms 呢
机房不卡代码插入了 好评如潮
题目的算法似乎马上就能猜到的样子…… AC 自动机 + 数位 dp
先暴力转移出 f[i][j] :表示从 AC 自动机上第 j 号节点走 i 步且不碰到匹配串的方案数
然后直接用数位 dp 一位一位的试就可以了,大家都会吧~
但是…… 有前导 0 的情况真尼玛蛋疼啊!
忽的灵光一闪……
前导 0 仅能影响长度小于 L 的数的统计
那么所有长度 <L 的数全部专门暴力统计一边不就可以了!我真是特么太机智了喵~ O(∩_∩)O~
虽然有个 O(10*L*l) 的转移 但是只跑了 272 ms 呢
#include <cstdio> #include <cstring> #define ord(ch) ((ch)-'0') const int sizeOfLength=1201; const int sizeOfNumber=1501; const int sizeOfType=10; const int mod=1000000007; struct node { int idx; bool end; node * fail, * ch[sizeOfType]; }; node * dfa; node memory[sizeOfNumber], * port=memory; inline node * newnode(); inline void insert(char * , int); node * q[sizeOfNumber]; int l, r; inline void build(); inline void dynamicprogramming(); char N[sizeOfLength]; int L; int M; int f[sizeOfLength][sizeOfNumber]; char s[sizeOfNumber]; int len; inline int getint(); inline int getstr(char * ); inline void putint(int); int main() { int ans=0; bool find=true; node * t; L=getstr(N); M=getint(); dfa=newnode(); for (int i=1;i<=M;i++) { len=getstr(s); insert(s, len); } build(); dynamicprogramming(); t=dfa; for (int i=0;i<L;i++) { for (int j=(i==0);j<ord(N[i]);j++) if (!t->ch[j]->end) ans=(ans+f[L-i-1][t->ch[j]->idx])%mod; t=t->ch[ord(N[i])]; if (t->end) { find=false; break; } } for (int i=L-2;i>=0;i--) for (int j=1;j<=9;j++) ans=(ans+f[i][dfa->ch[j]->idx])%mod; putint(ans+find); return 0; } inline int getint() { register int num=0; register char ch; do ch=getchar(); while (ch<'0' || ch>'9'); do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9'); return num; } inline int getstr(char * str) { register int len=0; register char ch; do ch=getchar(); while (ch<'0' || ch>'9'); do str[len++]=ch, ch=getchar(); while (ch>='0' && ch<='9'); return len; } inline void putint(int num) { char stack[11]; register int top=0; for ( ;num;num/=10) stack[++top]=num%10+'0'; for ( ;top;top--) putchar(stack[top]); putchar('\n'); } inline node * newnode() { node * ret=port++; ret->idx=port-memory-1; ret->fail=NULL; memset(ret->ch, 0, sizeof ret->ch); return ret; } inline void insert(char * s, int l) { node * t=dfa; for (int i=0;i<l;i++) { if (!t->ch[ord(s[i])]) t->ch[ord(s[i])]=newnode(); t=t->ch[ord(s[i])]; } t->end=true; } inline void build() { dfa->fail=dfa; for (int i=0;i<sizeOfType;i++) if (dfa->ch[i]) { dfa->ch[i]->fail=dfa; q[r++]=dfa->ch[i]; } else dfa->ch[i]=dfa; for ( ;l<r;l++) { node * u=q[l]; u->end|=u->fail->end; for (int i=0;i<sizeOfType;i++) if (u->ch[i]) { u->ch[i]->fail=u->fail->ch[i]; q[r++]=u->ch[i]; } else u->ch[i]=u->fail->ch[i]; } } inline void dynamicprogramming() { int tot=port-memory; for (int i=0;i<tot;i++) if (!(dfa+i)->end) f[0][(dfa+i)->idx]=1; for (int i=1;i<=L;i++) for (int j=0;j<tot;j++) if (!(dfa+j)->end) for (int k=0;k<sizeOfType;k++) f[i][(dfa+j)->idx]=(f[i][(dfa+j)->idx]+f[i-1][(dfa+j)->ch[k]->idx])%mod; }
机房不卡代码插入了 好评如潮
相关文章推荐
- [BZOJ3530][SDOI2014]数数(AC自动机+数位dp)
- bzoj 3530: [Sdoi2014]数数 数位dp
- BZOJ3530 [SDOI2014]数数
- [BZOJ3530][Sdoi2014]数数(AC自动机上数位DP)
- bzoj 3530 : [Sdoi2014]数数
- 【bzoj3530】【sdoi2014】【数数】【AC自动机+数位dp】
- bzoj 3530: [Sdoi2014]数数 AC自动机&动态规划
- [BZOJ3530][SDOI2014]数数 AC自动机+数位DP
- bzoj 3530: [Sdoi2014]数数 (AC自动机+数位DP)
- BZOJ 3530: [Sdoi2014]数数 (关于记忆化哪些元素的选择)
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位dp)
- [BZOJ 3530] [Sdoi2014] 数数 【AC自动机+DP】
- 【BZOJ 3530】 [Sdoi2014]数数
- [BZOJ3530][SDOI2014]数数
- bzoj 3530 [Sdoi2014]数数
- 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp
- bzoj 3530: [Sdoi2014]数数
- [bzoj3530][SDOI2014]数数
- 【BZOJ 3530】【SDOI 2014】数数
- Bzoj3530 [Sdoi2014]数数