题目链接:Click here~~
题意:
找一个 n 的最小倍数 x,使 x 中不包含 m 个指定的数字。
解题思路:
做过一道类似的题目。
由于只需要不包含指定集合中的数字,那么考虑从高位到低位枚举时,每次的选择都是互不影响的,所以设计状态 dp[mod] 表示当前余数为 mod 时的解。
搜索时每位都从小到大枚举,保证了第一次扩展到的一定就是能到达这个状态的最小的数。这样复杂度才 O(10^4 * 10)。
Ps. 时限应该多打了个 0 吧。=.=
#include <queue>
#include <string>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 1e4 + 5;
#define CLR(a,v) memset(a,v,sizeof(a))
bool vis[N],del[10];
int n,pre[N];
char ansAt[N];
bool bfs()
{
queue<int> Q;
Q.push(0);
while(!Q.empty())
{
int cur = Q.front();Q.pop();
for(int i=0;i<10;i++)
{
if(del[i] || cur == 0 && i == 0)
continue;
int nxt = (cur * 10 + i) % n;
if(vis[nxt])
continue;
ansAt[nxt] = '0' + i;
vis[nxt] = true;
pre[nxt] = cur;
Q.push(nxt);
if(nxt == 0)
return true;
}
}
return false;
}
void print_ans()
{
string ans;
int p = 0;
while(p != 0 || ans.empty())
{
ans += ansAt[p];
p = pre[p];
}
reverse(ans.begin(),ans.end());
puts(ans.c_str());
}
int main()
{
//freopen("out.ads","w",stdout);
int m,ncase = 0;
while(~scanf("%d%d",&n,&m))
{
CLR(vis,false);
CLR(del,false);
while(m--)
{
int k;
scanf("%d",&k);
del[k] = true;
}
printf("Case %d: ",++ncase);
if(!bfs())
puts("-1");
else
print_ans();
}
return 0;
}