比较恶心的题目
不难发现是在自动机上做数位dp
注意要考虑前导0,题目中给出的233是幸运数,20233不是
为此我非常猥琐的写了一个四维dp,用记忆化搜索实现
1 const mo=1000000007; 2 var dp:array[0..1,0..1,0..1205,0..1505] of longint; 3 trie:array[0..2005,'0'..'9'] of longint; 4 q,f:array[0..2005] of longint; 5 can:array[0..2005] of boolean; 6 ans,i,n,m,t,j,k,l:longint; 7 s,ss:ansistring; 8 ch:char; 9 10 procedure ac; 11 var h,r,i,x,y:longint; 12 c:char; 13 begin 14 h:=1; 15 r:=0; 16 for c:='0' to '9' do 17 if trie[0,c]>0 then 18 begin 19 inc(r); 20 q[r]:=trie[0,c]; 21 end; 22 23 while h<=r do 24 begin 25 x:=q[h]; 26 for c:='0' to '9' do 27 if trie[x,c]>0 then 28 begin 29 y:=trie[x,c]; 30 inc(r); 31 q[r]:=y; 32 j:=f[x]; 33 while (j>0) and (trie[j,c]=0) do j:=f[j]; 34 f[y]:=trie[j,c]; 35 if can[trie[j,c]] then can[y]:=true; //注意 36 end; 37 inc(h); 38 end; 39 end; 40 41 function calc(p,z,i,j:longint):longint; //p表示当前位置上的数是否需要小于N当前位上的数 42 //z表示假如当前位出现0,是否是多余的0 43 var k,q,zz:longint; 44 s,c,e:char; 45 begin 46 if can[j] then exit(0); 47 if i=m then exit(1); 48 if dp[p,z,i,j]<>-1 then exit(dp[p,z,i,j]); 49 dp[p,z,i,j]:=0; 50 if p=0 then e:=ss[i+1] else e:='9'; 51 for c:='0' to e do 52 begin 53 if (p=0) and (c=e) then q:=0 54 else q:=1; 55 k:=j; 56 while k>-1 do 57 begin 58 if trie[k,c]>0 then break; 59 k:=f[k]; 60 end; 61 if k=-1 then k:=0 else k:=trie[k,c]; 62 if (z=0) and (c='0') then //开头多余的0不考虑 63 begin 64 zz:=0; 65 k:=0; //多余的0不在自动机上匹配 66 end 67 else zz:=1; 68 dp[p,z,i,j]:=(dp[p,z,i,j]+calc(q,zz,i+1,k)) mod mo; 69 end; 70 exit(dp[p,z,i,j]); 71 end; 72 73 begin 74 read(ch); 75 while ch='0' do read(ch); 76 readln(ss); 77 ss:=ch+ss; 78 m:=length(ss); 79 f[0]:=-1; 80 readln(n); 81 for i:=1 to n do 82 begin 83 readln(s); 84 j:=0; 85 l:=length(s); 86 for k:=1 to l do 87 begin 88 if trie[j,s[k]]=0 then 89 begin 90 inc(t); 91 trie[j,s[k]]:=t; 92 end; 93 j:=trie[j,s[k]]; 94 end; 95 can[j]:=true; 96 end; 97 ac; 98 fillchar(dp,sizeof(dp),255); 99 ans:=(calc(0,0,0,0)-1+mo) mod mo; 100 writeln(ans); 101 end.