【链接】:
https://odzkskevi.qnssl.com/fa6682426fb11e87a5ab9246f22a461d?v=1535768440
【题意】:
给你一个包含数字和问号的字符串,在问好处填数字,使得最小的数能被n整除
|s|<=1e3,n<=1e3
【思路】:
暴力dfs+记忆化,每个点状态:[现在的位数][现在的模数],1000*1000的状态记忆化一下,每次只会遍历到一次。
【代码】:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 6;
char s[maxn];
string ans;
int vis[maxn][maxn], flag[maxn][maxn];
int n;
int len;
int dfs(int now, int mod) {
if (now == len)return mod == 0;
if (vis[now][mod] != -1)return flag[now][mod];
vis[now][mod] = 1;
int &ret = flag[now][mod];
if (s[now] == '?') {
for (int i = !now; i <= 9; i++) {
ret |= dfs(now + 1, (mod * 10 + i) % n);
if (ret)return 1;
}
return 0;
}
else {
ret |= dfs(now + 1, (mod * 10 + s[now] - '0') % n);
return ret;
}
}
void f(int now, int mod) {
if (now == len) return;
if (s[now] == '?') {
for (int i = !now; i < 10; i++) {
if (dfs(now + 1, (mod * 10 + i) % n)) {
ans += '0' + i;
f(now + 1, (mod * 10 + i) % n);
return;
}
}
}
else {
ans += s[now];
f(now + 1, (mod * 10 + s[now] - '0') % n);
return;
}
}
int main() {
scanf("%s", s);
scanf("%d", &n);
len = strlen(s);
memset(vis, -1, sizeof(vis));
memset(flag, 0, sizeof(flag));
if (dfs(0, 0)) {
f(0, 0);
cout << ans << endl;
}
else printf("*\n");
}