【BZOJ】【3530】【SDOI2014】数数

AC自动机/数位DP


  orz zyf

  好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱……

 1 /**************************************************************
 2     Problem: 3530
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:1008 ms
 7     Memory:33956 kb
 8 ****************************************************************/
 9  
10 //BZOJ 3530
11 #include<vector>
12 #include<cstdio>
13 #include<cstring>
14 #include<cstdlib>
15 #include<iostream>
16 #include<algorithm>
17 #define rep(i,n) for(int i=0;i<n;++i)
18 #define F(i,j,n) for(int i=j;i<=n;++i)
19 #define D(i,j,n) for(int i=j;i>=n;--i)
20 #define pb push_back
21 using namespace std;
22 inline int getint(){
23     int v=0,sign=1; char ch=getchar();
24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
26     return v*sign;
27 }
28 const int N=2015,INF=~0u>>2,MOD=1e9+7;
29 typedef long long LL;
30 /******************tamplate*********************/
31 int n,m,cnt=1,a[N];
32 struct Trie{
33     int ch[10],fail;
34     bool sign;
35 }T[N*10];
36 char s[N],s1[N];
37 void ins(){
38     scanf("%s",s1);
39     int x=1,y;
40     rep(i,strlen(s1)){
41         y=s1[i]-'0';
42         if (!T[x].ch[y]) T[x].ch[y]=++cnt;
43         x=T[x].ch[y];
44     }
45     T[x].sign=1;
46 }
47 int Q[N];
48 void make_fail(){
49     int l=0,r=-1,j;
50     Q[++r]=1;
51     while(l<=r){
52         int x=Q[l++],y;
53         T[x].sign|=T[T[x].fail].sign;
54         rep(i,10){
55             j=T[x].fail;
56             while(j && T[j].ch[i]==0) j=T[j].fail;
57             if (T[x].ch[i]){
58                 y=T[x].ch[i];
59                 T[y].fail=j ? T[j].ch[i] : 1;
60                 Q[++r]=y;
61             }else T[x].ch[i]=j ? T[j].ch[i] : 1;
62         }
63     }
64 }
65 int f[N][N][2];
66 int main(){
67 #ifndef ONLINE_JUDGE
68     freopen("3530.in","r",stdin);
69     freopen("3530.out","w",stdout);
70 #endif
71     scanf("%s",s);
72     n=strlen(s);
73     F(i,1,n) a[i]=s[i-1]-'0';
74     m=getint(); cnt=1;
75     F(i,0,9) T[1].ch[i]=++cnt;
76     F(i,1,m) ins();
77     make_fail();
78  
79     F(i,1,a[1]) 
80         if(!T[T[1].ch[i]].sign) f[1][T[1].ch[i]][i==a[1]]=1;
81     F(i,1,n-1) F(j,1,cnt){
82         F(k,0,a[i+1]) if(!T[T[j].ch[k]].sign)
83             (f[i+1][T[j].ch[k]][k==a[i+1]]+=f[i][j][1])%=MOD;
84         rep(k,10) if(!T[T[j].ch[k]].sign)
85             (f[i+1][T[j].ch[k]][0]+=f[i][j][0])%=MOD;
86     }
87     int ans=0;
88     F(i,1,cnt) (ans+=f[n][i][0])%=MOD,(ans+=f[n][i][1])%=MOD;
89  
90     memset(f,0,sizeof f);
91     F(i,1,9) if (!T[T[1].ch[i]].sign) f[1][T[1].ch[i]][0]=1;
92     F(i,1,n-2) F(j,1,cnt)
93         rep(k,10) if(!T[T[j].ch[k]].sign)
94             (f[i+1][T[j].ch[k]][0]+=f[i][j][0])%=MOD;
95     F(i,1,n-1) F(j,1,cnt)
96         (ans+=f[i][j][0])%=MOD;
97     printf("%d\n",ans);
98     return 0;
99 }
View Code

3530: [Sdoi2014]数数

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 404  Solved: 241
[Submit][Status][Discuss]

Description

我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
    给定N和S,计算不大于N的幸运数个数。

Input


    输入的第一行包含整数N。
    接下来一行一个整数M,表示S中元素的数量。
    接下来M行,每行一个数字串,表示S中的一个元素。

Output

    输出一行一个整数,表示答案模109+7的值。

Sample Input

20
3
2
3
14

Sample Output

14

HINT

 下表中l表示N的长度,L表示S中所有串长度之和。


1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500

Source

[Submit][Status][Discuss]
posted @ 2015-04-06 16:27  Tunix  阅读(283)  评论(0编辑  收藏  举报