更新:整合 Ante 的观察结果并将答案社区设为 wiki。
像往常一样,在这类问题中,编写任何可行的蛮力算法都相对容易,但更多的是数学。你用铅笔和纸做,你可以获得更好(更快)的算法。
让我们使用简写符号:让 M(i) 表示 1111...1(i 个)。
给定一个数 n(假设 n = 23),你想找到一个数 m,使得 M(m) 可以被 n 整除。一个直接的方法是检查 1, 11, 111, 1111, ... 直到我们找到一个能被 n 整除的数。注意:可能存在 closed-form solution 用于在给定 n 的情况下找到 m,因此这种方法不一定是最佳的。
当迭代 M(1), M(2), M(3), ... 时,有趣的部分显然是如何检查给定数是否可被 n 整除。你可以实现long division,但arbitrary-precision arithmetic 很慢。相反,请考虑以下事项:
假设您从之前的迭代中已经知道M(i) mod n 的值。如果M(i) mod n = 0,那么你就完成了(M(i) 是答案),所以我们假设它不是。你想找到M(i+1) mod n。由于M(i+1) = 10 * M(i) + 1,您可以轻松计算M(i+1) mod n,因为它是(10 * (M(i) mod n) + 1) mod n。即使对于较大的 n 值,也可以使用固定精度算术计算。
这是一个计算可被 n 整除的最小数目的函数(从 Ante 的 Python 答案翻译为 C):
int ones(int n) {
int i, m = 1;
/* Loop invariant: m = M(i) mod n, assuming n > 1 */
for (i = 1; i <= n; i++) {
if (m == 0)
return i; /* Solution found */
m = (10*m + 1) % n;
}
return -1; /* No solution */
}