http://poj.org/problem?id=1465
题目大意:
给你一个n 再给你m 个一位整数 问用这m个数
可以组合出最小的n的倍数 没有则输出 0
bfs + 余数剪枝 相同余数不能出现两次
m个数需要排序 才能保证最小
中间可能出现大整数 要处理
代码及其注释:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<cstring>
#include<set>
#include<string>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int N=1005;
bool had[N*5];//标记是否此余数是否出现过
string a[12];
queue<string>str;//防止大整数情况
int MOD(string s,int n)//求余数
{
int k=0;
for(int i=0;i<s.size();++i)
{
k=(k*10+s[i]-'0')%n;
}
return k;
}
int main()
{
//freopen("data.txt","r",stdin);
int n,m;
while(cin>>n>>m)
{
while(!str.empty())
str.pop();
memset(had,false,sizeof(had));
for(int i=0;i<m;++i)
{
cin>>a[i];
}
if(n==0)//0 要特判
{
printf("0\n");
continue;
}
sort(a,a+m);//排序
string ans="0";
int i;
for(i=0;i<m;++i)
{
if(a[i]!="0")
{
int l=MOD(a[i],n);
if(l==0)//余数为0 的话直接跳出循环
{
ans=a[i];
break;
}
if(!had[l])//去重
{
had[l]=true;
str.push(a[i]);
}
}
}
if(i>=m)//需要继续广搜
while(!str.empty())
{
string x=str.front();//cout<<x<<endl;
str.pop();
int j;
for(j=0;j<m;++j)
{
string k=x+a[j];
int l=MOD(k,n);
if(had[l]==false)//余数不能重
{
had[l]=true;
if(l==0)//发现合适的 知道跳出循环
{
ans=k;
break;
}
str.push(k);
}
}
if(j<m)
break;
}//cout<<endl;
cout<<ans<<endl;
}
return 0;
}
浙公网安备 33010602011771号