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; }