题意
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
做法
建好ac自动机后 进行数位dp 即可
注意要有前导零
最终状态就是 最后的ac自动机上的u点没有标记
记数即可
最后要减去 0
因为
范围从1 开始
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb push_back
#define inf 1<<62
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
const int mod = 1e9 + 7;
const int N = 1e4 + 10;
int n, m;
struct acam {
struct node {
int fail;
int f = 0;
int son[26] = {};
} trie[N];
int idx = 0;
void insert(string &s) {
int u = 0;
for(auto c : s) {
if(!trie[u].son[c - '0']) {
trie[u].son[c - '0'] = ++idx;
}
u = trie[u].son[c - '0'];
}
trie[u].f = 1;
}
ll dp[1210][1530][2][2];
void build() {
queue<int>q;
for(int i = 0; i <= 25; i++) {
if(trie[0].son[i]) {
q.push(trie[0].son[i]);
}
}
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = 0; i <= 25; i++) {
int v = trie[u].son[i], fa = trie[trie[u].fail].son[i];
if(trie[u].son[i]) {
trie[v].fail = fa;
q.push(v);
} else {
trie[u].son[i] = trie[trie[u].fail].son[i];
}
}
trie[u].f |= trie[trie[u].fail].f;
}
}
void reset() {
memset(dp, -1, sizeof(dp));
}
string a;
ll dfs(int len, int u, int le, int lim ) {
if(len == a.size())return !trie[u].f;
if(dp[len][u][lim][le] != -1 && !le && !lim)return dp[len][u][lim][le];
int up = lim ? (a[len] - '0' ) : 9;
ll ans = 0;
for(int i = 0; i <= up; i++) {
if(le && !i)ans = (ans + dfs(len + 1, 0, 1, lim && (i == up) )) % mod;
else {
if( trie[trie[u].son[i]] .f )continue;
ans = (ans + dfs(len + 1, trie[u].son[i] , 0, lim && (i == up) )) % mod;
}
}
if(!le && !lim) dp[len][u][lim][le] = ans;
return ans;
}
} AC;
void solve() {
cin >> AC.a;
AC.reset();
cin >> n ;
for(int i = 1; i <= n; i++) {
string s;
cin >> s;
AC.insert(s);
}
AC.build();
cout << (AC.dfs(0, 0, 1, 1) - 1 + mod) % mod;
}
int main() {
IOS;
int _ = 1;
//cin>>_;
while( _-- )
solve();
}