您可以使用类似于求平方的算法来解决这个问题。
首先,如果你有偶数个 1,你可以看到:
11111111 = 1111 * 10001
n ones n/2 ones (10^(n/2) + 1)
使个数加倍。还有,
1111111 = 111111 * 10 + 1
n ones n-1 ones
将这些观察结果形式化,并为方便起见将 n 个 111...1 的数字命名为 J(n):
- 如果 n 是偶数,则 J(n) = (10^(n/2) + 1)J(n/2)。
- 如果 n 是奇数,J(n) = 10*J(n-1) + 1。
您可以使用这些递推式(加上通过平方计算 10^(n/2) 的求幂的实际实现)模 M 以 O(log(n)^2) 时间计算结果。
这里有一些实现这一点的 C 代码。如果你想要一个大的M,你必须使用比int更长的类型来避免溢出(你需要M^2来适应你的类型)。
#include <stdio.h>
// Computes a to the power of n modulo m.
int pow_mod_m(int a, int n, int m) {
if (n == 0) { return 1; }
if (n == 1) { return a; }
if (n % 2 == 0) {
int k = pow_mod_m(a, n/2, m);
return (k * k) % m;
}
return (pow_mod_m(a, n-1, m) * a) % m;
}
// Computes J(n) modulo m
int j_mod_m(int n, int m) {
if (n == 1) {
return 1;
}
if (n % 2 == 0) {
return (j_mod_m(n/2, m) * (1 + pow_mod_m(10, n/2, m))) % m;
}
return (j_mod_m(n-1, m) * 10 + 1) % m;
}
int main(int argc, char**argv) {
for (int i = 1; i < 1000; i++) {
printf("%d: %d\n", i, j_mod_m(i, 12345));
}
return 0;
}