lc1015-可被K整除的最小整数
题目描述
- 给定正整数 k,找出最小的一个数字,满足
- 仅由 1 组成
- 可以被 k 整除
- 找到,返回数字长度;找不到返回 -1
示例
输入:k = 1
输出:1
解释:数字是 1,其长度为 1
输入:k = 2
输出:-1
输入:k = 3
输出:3
解释:数字是 111,其长度为 3
题解
- 思路
模拟
- O(n)
func smallestRepunitDivByK(k int) int {
if k % 2 == 0 || k % 5 == 0 { return -1 }
for i, x := 1, 1 % k; ; i ++ {
if x == 0 { return i }
x = (x * 10 + 1) % k
}
}
欧拉定理
\(O(\sqrt{n} \times \log_{2}{n})\)
\[\begin{aligned}
111...1 &= \frac{10^x - 1}{9} \\
k &\mid \frac{10^x - 1}{9} \\
9k &\mid 10^x - 1 \\
10^x &\equiv 1 \pmod{9k}
\end{aligned}
\]
- => 10 与 9k 互质
- => 10 与 k 互质
- => k 不能有因子 2, 5
\[\begin{aligned}
欧拉定理:\\
a^{\phi(n)} &\equiv 1 \pmod{n} \\
\Rightarrow x &= \phi(9k)
\end{aligned}
\]
func smallestRepunitDivByK(k int) int {
if k % 2 == 0 || k % 5 == 0 { return -1 }
phi := get_euler(9 * k)
res := phi
for i := 1; i * i <= phi; i ++ {
if phi % i == 0 {
if qmi(10, i, 9 * k) == 1 { return i }
if qmi(10, phi / i, 9 * k) == 1 { res = min(res, phi / i) }
}
}
return res
}
func get_euler(x int) int {
res := x
for i := 2; i * i <= x; i ++ {
if x % i == 0 {
res = res / i * (i - 1)
for x % i == 0 { x /= i }
}
}
if x > 1 { res = res / x * (x - 1) }
return res
}
func qmi(a, b, p int) int {
res := 1
for b > 0 {
if b & 1 == 1 { res = res * a % p }
a = a * a % p
b >>= 1
}
return res
}

浙公网安备 33010602011771号