25.11.25刷题日记 leetcode1015. 可被 K 整除的最小整数

25.11.25刷题日记 leetcode1015. 可被 K 整除的最小整数

题目链接:1015. 可被 K 整除的最小整数

题目描述:

image-20251125140944853

解题思路

这里的解题思路并不复杂,主要是一些数学推导方面的内容,我们需要利用的主要有抽屉原理,同时还有取模的一些优化。

暴力遍历思路:

首先我们不妨记:

R_{1} = 1,R_{2} = 11,.......,R_n = \underbrace{11\ldots1}_{n\ \text{个}}

它满足以下递推关系:

R_1 = 1, \qquad R_{n+1} = 10R_n + 1.

取模 k 后,定义
r_n \equiv R_n \pmod{k}.

由递推关系可得
r_1 \equiv 1 \pmod{k}, \qquad r_{n+1} \equiv 10 r_n + 1 \pmod{k}.

首先我们证明取模结果一定是一个循环序列:

序列 \{ r_n \} 的所有可能取值属于有限集合

\{0,1,2,\dots,k-1\}

k 个状态。由于序列无限,根据抽屉原理,必存在

1 \le i < j \le k+1 [/latex] <p>使得 [katex] r_i = r_j [/katex]</p> <p>由递推关系可写出展开式:</p> [latex] r_j \equiv 10^{\,j-i} r_i + \left( 10^{\,j-i-1} + 10^{\,j-i-2} + \cdots + 10 + 1 \right) \pmod{k}.

由于 r_j = r_i,两边相减得

0 \equiv 10^{\,j-i} r_i - r_i + \left( 10^{\,j-i-1} + \cdots + 10 + 1 \right)\pmod{k}.

这意味着从第 i 项开始,序列在每隔 $ T = j - i $ 项后重复一次:

r_{n+T} = r_n,\qquad \forall n \ge i.

因此序列 \{ r_n \} 为最终周期序列(eventually periodic),周期满足 T \le k

上面证明了最后R_i随着i的增加对k的模的结果一定是一个循环序列,所以我们暴力的做法就是:在没出现数字重复前判断是否有R_i mod k == 0。

对应代码:

class Solution:
    def smallestRepunitDivByK(self, k: int) -> int:
        dict1 = defaultdict(int)
        num = 1
        len = 1
        while num % k != 0:
            if dict1[num] != 0:
                return -1
            dict1[num] = 1
            num = (num%k)*10+1
            len += 1
        return len

优化思路:

由于待除数结尾全都是1组成,显然当k为2或者5的倍数时,此次是一定不能整除的,这里我们直接特判返回即可,那么我们题目的证明就转化为了:

证明当k不为2或者5的倍数时,一定存在某个i使得R_i 可以被k整除

接着上面的抽屉原理,当a>b时,存在

(R_a - R_b)\mod k =0

R_a - R_b = R_{a-b} * 10^{b}

则有:

( R_{a-b} * 10^{b})\mod k = 0

由k不为2或者5的倍数可得 k与10互质,不能得其也于10的指数也互质,这里我们不妨设 u为其的乘法逆元,则有:

10^b * u \equiv 1 (\mod k)

则有:

R_{a-b} * 10^{b}*u \equiv 0*u(\mod k)

则可得:

R_{a-b} \equiv 0(\mod k)

即i = a-b时,使得证明成立。

这里证明的好处在于由于我们证明可得除了特判情况外,其他情况一定有解,无需判断是否余数是否有循环了。

对应代码:

class Solution:
    def smallestRepunitDivByK(self, k: int) -> int:
        if k % 2 == 0 or k % 5 == 0:  # 如果 k 是 2 的倍数或者 5 的倍数,返回 -1
            return -1

        ans, resid = 1, 1  # ans 表示长度,resid 表示余数
        while resid % k != 0:  # 当余数不为 0 时
            resid = (resid % k) * (10 % k) + 1  # 模拟除法运算,计算下一次的余数
            ans += 1  # 长度加 1

        return ans  # 返回最小整数的长度
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇