ZOJ 3494 AC自動機 高精度數字DP

2021-09-08 10:28:22 字數 2051 閱讀 2242

題目鏈結

題目大意:給定一些被禁止的bcd碼。問指定範圍內不含有任何這些禁止的bcd碼的數的個數。

解題思路

ac自動機部分:

首先insert這些被禁止的bcd碼。

然後打一下自動機前後狀態的轉移的表,用bcd[i][j]表示自動機狀態i時,下乙個數字是j的自動機的下乙個狀態。

一開始我考慮最先dfs的位在自動機的位置,後來發現sb了。ac自動機有乙個root狀態,也就是自動機位置為0的狀態,使用這個0就行了。

即f函式中dfs(len,0,true,true),每次由root狀態出發,無須再考慮其它的。

數字dp部分:

本題的範圍是高精度範圍,所以需要特有的高精度寫法。

麻煩的在於f(l-1),要為高精度手艹乙個-1,有種偷懶的寫法,不過會導致出現前導0。

所以在傳統的dfs中需要增加乙個前導0的判斷。

方法是:追加乙個bool z,

在原有的0~9基礎上,單獨考慮0,

if(z) 則單獨dfs前導0

否則dfs正常的0,1~9照常dfs。當然還需要判斷當前狀態s的下乙個狀態bcd[s][i]是否符合要求。

然後最後就是注意一下負數mod。

#include "

cstdio

"#include

"cstring

"#include

"queue

"#include

"iostream

"using

namespace

std;

#define maxp 25*105

#define mod 1000000009

struct

trie

pool[maxp],*root,*sz;

int bcd[maxp][10],digit[205

],ccnt;

long

long dp[205

][maxp];

trie *newnode()

void

init()

void insert(string

str)

pos->cnt++;

}void

getfail()

else root->next[c]=root;

}while(!q.empty())

else x->next[c]=x->fail->next[c];}}

}int judge(int status,int

num)

return pos-pool;

}void

getbcd()

int dfs(int len,int s,bool fp,bool

z)

else

for(int i=1;i<=fpmax;i++)

if(!fp&&!z) dp[len][s]=ret;

return

ret;

}int f(string

str)

intmain()

getfail();

ccnt=sz-pool;

getbcd();

cin>>tt;

for(int i=tt.size()-1;i>=0;i--)

else

}long

long ans=0

; ans-=f(tt);

ans%=mod;

cin>>tt;

ans+=f(tt);

ans=(ans%mod+mod)%mod;

printf(

"%lld\n

",ans);

}}

2842327

neopenx

zoj 3494

accepted

4656 kb

210 ms

c++ (g++ 4.4.5)

2976 b

2014-10-13 17:06:35

ZOJ 3494 AC自動機 數字DP

有一種bcd編碼方案,求a到b範圍內的數字的bcd編碼有多少個不包含不能包含的字串。數字範圍這麼大,很明顯就能看出來是數字dp。基於ac自動機的數字dp使得數字dp容易了不少,因為ac自動機自帶狀態轉移。在數字dp選取每一位的時候,基於ac自動機狀態轉移一下,如果轉移到不能轉移的狀態,就直接返回 1...

zoj3494 ac自動機 數字dp

題解 把給的串建ac自動機,然後得到的bcd i j bcd i j 表示在ac自動機上的狀態i,後面加入j會轉移的狀態,1表示不能加 然後數字dp,dp i j 表示取到第i位狀態為j後面的數字隨便取的方案數,這裡是記憶化。include include include include inclu...

zoj3430 AC自動機模擬

jibancanyang author jibancanyang created time 五 5 6 16 14 59 2016 file name jy.cpp problem analyse 此題難就難在編碼,還有題意問的是病毒有多少種不是多少個,注意char已經不能表示解碼之後的字元,要用 ...