题目链接
https://vjudge.net/problem/Gym-101889E
题目大意
给定数字串和
k
k
k,数字串为
?
?
?的位置可以任意填
0
−
9
0-9
0−9,求最小的
%k
为0的数,没有则输出
∗
*
∗
1
≤
l
e
n
≤
1000
1 \leq len \leq 1000
1≤len≤1000 ,
1
≤
k
≤
1000
1\leq k \leq 1000
1≤k≤1000
题解思路
状态很多,不能直接暴搜。这题是求
∣
k
|k
∣k的最小数,可以记录余数表示状态从而减少总状态数。
用
d
p
[
p
o
s
]
[
l
e
f
]
dp[pos][lef]
dp[pos][lef]表示当前到第
p
o
s
pos
pos位,是否存在%
k
k
k为
l
e
f
lef
lef的状态,有则标记状态为1,相当于是一个
v
i
s
vis
vis数组。
然后从高位向低位记忆化搜索,注意不能出现前导0,对于
?
?
?的数位,每次标记该数位为
i
i
i,搜索完再标记回
?
?
?
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
//#define int ll
#define debug cout<<"fuck"<<endl;
#define pb push_back
#define endl '\n'
#define fi first
#define se second
#define db double
#define pii pair<int,int>
#define mp make_pair
#define mian main
#define whiel while
#define retrun return
const int mod=(int)1e9+7;
int add(int a, int b) {if((a += b) >= mod) a -= mod; return a < 0 ? a + mod : a;}
int mul(int a, int b) {return 1ll * a * b % mod;}
const int maxn=(int)1e3+5;
int n,k;
string s;
bool dp[maxn][maxn];
int okk=0;
void dfs(int pos,int lef)
{
if(pos==n)
{
if(lef==0)okk=1;
return;
}
if(s[pos]!='?')
{
int val=s[pos]-'0';
if(!dp[pos][(lef*10+val)%k])
{
dfs(pos+1,(lef*10+val)%k);
if (okk)return;
dp[pos][(lef*10+val)%k]=1;
}
}
else
{
int i;
i=((pos==0)?1:0);//保证没有前导0
for(;i<10;i++)
{
if(!dp[pos][(lef*10+i)%k])
{
s[pos] = '0' + i;
dfs(pos + 1, (lef * 10 + i) % k);
if (okk)return;
s[pos] = '?';
dp[pos][(lef * 10 + i) % k] = 1;
}
}
}
}
int main()
{
IOS
cin>>s>>k;
n=s.size();
dfs(0,0);
//debug
if(okk)cout<<s<<endl;
else cout<<'*'<<endl;
retrun 0;
}