搜索一个是n倍数的大数,bfs
求一个大数,满足是n的倍数,但是长度不超过500位。一开始以为搜索的状态有m^500,觉得无从下手。其实我们可以运用同模定理,所以状态最多是n,从0到n-1。
还有这里要保存路径,所以用数组来模拟队列,每个节点记录他父亲节点在数组队列中的下标值。
总结:1.大数问题,特别是涉及到倍数方面的,考虑下取模运算。
2.bfs搜索求路径时,用数组模拟队列取代queue。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Node { int val, mod; //记录当前点的值与对n的取模值 int idx, pre; //记录当前点的下标与父亲节点的下标 int deep; //记录深度,即数字的长度 }ns[500005]; int end, n, type, m; int num[20]; void init() { int i; char ch[10]; scanf( "%d %d", &n, &type ); scanf( "%d", &m ); for( i=1; i<=m; ++i ) { scanf( "%s", ch ); if( ch[0] >= 'A' && ch[0] <= 'F' ) num[i] = 10 + ch[0] - 'A'; else num[i] = ch[0] - '0'; } } bool canEnd() { bool flag = false; for(int i=1; i<=m; ++i ) if( num[i] == 0 ) flag = true; if( n == 0 ) { if( flag ) printf( "0\n" ); else puts( "give me the bomb please" ); return 1; } return 0; } void output( int s ) { if( ns[s].pre != s ) output( ns[s].pre ); printf( "%X", ns[s].val ); } void solve() { int i, j, head, mm; bool mark[5001]; Node p, q; if( canEnd() ) return; memset( mark, 0, sizeof(mark) ); sort( num+1, num+m+1 ); end = 0; for( i=1; i<=m; ++i ) { if( num[i] == 0 ) continue; ns[end].val = num[i]; ns[end].mod = num[i] % n; ns[end].idx = ns[end].pre = end; ns[end].deep = 1; mark[ns[end].mod] = 1; ++ end; } head = 0; while( head < end ) { p = ns[head]; ++head; if( p.mod == 0 ) { output( p.idx ); printf( "\n" ); return; } for( i=1; i<=m; ++i ) { q.val = num[i]; q.mod = (p.mod*type + num[i]) % n; q.idx = end; q.pre = p.idx; q.deep = p.deep + 1; if( mark[q.mod] ) continue; if( q.deep >= 500 && q.mod != 0 ) continue; ns[end++] = q; mark[q.mod] = 1; } } puts( "give me the bomb please" ); } int main() { // freopen( "c:/aaa.txt", "r", stdin ); int T; scanf( "%d", &T ); while( T-- ) { init(); solve(); } return 0; }