題解:把給的串建ac自動機,然後得到的bcd[i][j],bcd[i][j]表示在ac自動機上的狀態i,後面加入j會轉移的狀態,-1表示不能加
然後數字dp,dp[i][j]表示取到第i位狀態為j後面的數字隨便取的方案數,這裡是記憶化。
#include#include#include
#include
#include
#include
#include
#include
#define pb push_back
#define mk make_pair
#define ll long long
#define fi first
#define se second
#define pi 3.14159265
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define eps 1e-7
#define pii pair#define pll pairtypedef unsigned
long
long
ull;
const
int mod=1000000009
;const ll inf=0x3f3f3f3f3f3f3f
;const
int n=2e3+100
;using
namespace
std;
char s[300
];int
n;struct
ac_auto
void
init()
intnew_node()
void insert(char *s)
ed[p]=1
; }
void
build()
while(!q.empty())}}
}ac;
int bcd[n][10
];int judge(int x,int
y)
returnx;}
void
slove()
}}ll dp[
210][n];
int bit[300
];ll dfs(
int p,int s,int flag,int z)//
p第幾位,s當前的狀態,flag是否已經有高位小於s,前面是否有非0值
else
int lim=(flag?bit[p]:9
);
for(int i=1;i<=lim;i++)
if(!flag&&!z)dp[p][s]=ans;
return
ans;
}ll
get(char *s)
return dfs(len-1,0,1,1);}
intmain()
ac.build();
slove();
scanf("%s
",s);
int len=strlen(s);
for(int i=len-1;i>=0;i--)
else s[i]='9'
; }
ll ans=0
; ans-=get
(s);
ans%=mod;
scanf("%s
",s);
ans+=get
(s);
ans%=mod;
if(ans<0)ans+=mod;
printf(
"%lld\n
",ans);
}return0;
}/*12 1 2
1 21 1 1
2 1 2
*/
ZOJ 3494 AC自動機 數字DP
有一種bcd編碼方案,求a到b範圍內的數字的bcd編碼有多少個不包含不能包含的字串。數字範圍這麼大,很明顯就能看出來是數字dp。基於ac自動機的數字dp使得數字dp容易了不少,因為ac自動機自帶狀態轉移。在數字dp選取每一位的時候,基於ac自動機狀態轉移一下,如果轉移到不能轉移的狀態,就直接返回 1...
ZOJ 3494 AC自動機 高精度數字DP
題目鏈結 題目大意 給定一些被禁止的bcd碼。問指定範圍內不含有任何這些禁止的bcd碼的數的個數。解題思路 ac自動機部分 首先insert這些被禁止的bcd碼。然後打一下自動機前後狀態的轉移的表,用bcd i j 表示自動機狀態i時,下乙個數字是j的自動機的下乙個狀態。一開始我考慮最先dfs的位在...
zoj3430 AC自動機模擬
jibancanyang author jibancanyang created time 五 5 6 16 14 59 2016 file name jy.cpp problem analyse 此題難就難在編碼,還有題意問的是病毒有多少種不是多少個,注意char已經不能表示解碼之後的字元,要用 ...