[Sdoi2014]數數
阿新 • • 發佈:2019-03-06
sta lse scrip ace oot make get stream tin
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\leqslant l\leqslant1200,1\leqslant M\leqslant100,1\leqslant L\leqslant1500\)
首先對集合\(S\)建AC自動機,然後考慮dp,設\(f[i][j][0/1]\)表示目前匹配到第\(i\)位,在AC自動機上的第\(j\)位,數是否頂在上界\(N\)的方案數
轉移則非常簡單,具體可以見代碼,分是否在上界兩種情況討論即可
然後建fail指針的時候沒有下傳標識符導致WA掉……
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline char gc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline int frd(){ int x=0,f=1;char ch=gc(); for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline int read(){ int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x<0) putchar('-'),x=-x; if (x>9) print(x/10); putchar(x%10+'0'); } const int N=1.5e3,M=1.2e3,Mod=1e9+7; struct S1{ int trie[N+10][10],fail[N+10],root,tot; bool End[N+10]; void insert(char *s){ int len=strlen(s),p=root; for (int i=0;i<len;i++){ if (!trie[p][s[i]-'0']) trie[p][s[i]-'0']=++tot; p=trie[p][s[i]-'0']; } End[p]=1; } void make_fail(){ static int h[N+10]; int head=1,tail=0; for (int i=0;i<10;i++) if (trie[root][i]) h[++tail]=trie[root][i]; for (;head<=tail;head++){ int Now=h[head]; End[Now]|=End[fail[Now]];//之前沒有下傳標識符…… for (int i=0;i<10;i++){ if (trie[Now][i]){ int son=trie[Now][i]; fail[son]=trie[fail[Now]][i]; h[++tail]=son; }else trie[Now][i]=trie[fail[Now]][i]; } } trie[root][0]=0; } }AC;//Aho-Corasick automaton int f[M+10][N+10][2]; char T[M+10]; int main(){ scanf("%s",T+1); int n=read(),len=strlen(T+1); for (int i=1;i<=len;i++) T[i]-='0'; for (int i=1;i<=n;i++){ static char s[N+10]; scanf("%s",s); AC.insert(s); } AC.make_fail(); f[0][0][1]=1; for (int i=0;i<len;i++){ for (int j=0;j<=AC.tot;j++){ for (int l=0;l<2;l++){ if (!f[i][j][l]) continue; for (int k=l?T[i+1]:9;~k;k--){ int son=AC.trie[j][k]; if (AC.End[son]) continue; f[i+1][son][l&(k==T[i+1])]=(f[i+1][son][l&(k==T[i+1])]+f[i][j][l])%Mod; } } } } ui Ans=Mod-1; for (int i=0;i<=AC.tot;i++) Ans=(Ans+f[len][i][0]+f[len][i][1])%Mod; printf("%u\n",Ans); return 0; }
[Sdoi2014]數數