poj1426 Find The Multiple
这题直接 \(bfs\) 居然能过是我没想到的。
/**
* poj1426 Find The Multiple
*
*/
#include <cstdio>
#include <queue>
using namespace std;
typedef long long LL;
LL bfs(int n)
{
queue<LL> Q;
Q.push(1);
while (!Q.empty()) {
LL t = Q.front(); Q.pop();
if (t % n == 0) return t;
Q.push(t*10);
Q.push(t*10+1);
}
return 0;
}
int main()
{
int n;
while (scanf("%d", &n) && n) {
printf("%lld\n", bfs(n));
}
return 0;
}
这是因为 \(n \le 200\) 时,最小答案恰好在 \(long\ long\) 范围内, 如果数据范围稍微大点,例如 \(n = 396\) 时,这个答案就不对了。
因此,更严谨的 \(AC\) 代码应该是这样的:
/**
* poj1426 Find The Multiple
* 还没有找到合适的剪枝方法
*/
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef long long LL;
const int M = 105, N = 400;
char out[M]; // 存储待输出的倍数
bool book[N]; // 记录mod是否被搜过
int pos;
// 返回true代表已找到答案
bool dfs(int mod, int n)
{
mod %= n;
// if (book[mod]) return false;
if (pos > 100) return false; // 题目说了不超过100位
if (mod == 0) return true;
// book[mod] = 1;
out[pos++] = '0';
if (dfs(mod*10, n)) return true;
--pos;
out[pos++] = '1';
if (dfs(mod*10+1, n)) return true;
--pos;
return false;
}
int main()
{
int n;
while (scanf("%d", &n) && n) {
memset(book, 0, sizeof book);
pos = 0;
out[pos++] = '1';
if (dfs(1, n)) out[pos] = 0, puts(out);
else puts("-1");
}
return 0;
}
虽然解空间看似有 \(2^{100}\) 种情况,但我们真正要搜索的次数不足 \(2^{22}\) ,别问数字怎么来的,实践出真知。
目前不知道该怎么从数学角度证明最小答案的长度远小于 \(100\) 字符。

浙公网安备 33010602011771号