Skip to content

Commit 1b89825

Browse files
committed
Add: Add 2025/11/25
1 parent c7d09a8 commit 1b89825

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# 1015. Smallest Integer Divisible by K
2+
3+
Given a positive integer `k`, you need to find the length of the smallest positive integer `n` such that n is divisible by `k`, and `n` only contains the digit `1`.
4+
5+
Return the length of `n`.
6+
If there is no such `n`, return -1.
7+
8+
Note: `n` may not fit in a 64-bit signed integer.
9+
10+
**Constraints:**
11+
12+
- `1 <= k <= 10^5`
13+
14+
## 基礎思路
15+
16+
本題要找的是一個**只由數字 `1` 組成的正整數 `n`**(例如:`1`, `11`, `111`, ...),
17+
使得它能被給定的正整數 `k` 整除,並回傳這個 `n` 的「位數長度」。若不存在則回傳 `-1`
18+
19+
關鍵觀察有以下幾點:
20+
21+
1. **數字結構固定為「重複的 1」**
22+
第 1 個候選是 `1`,第 2 個是 `11`,第 3 個是 `111`,依此類推。
23+
這些數字可以用遞推的方式建立:
24+
25+
* $R_1 = 1$
26+
* $R_2 = 11 = (R_1 * 10 + 1)$
27+
* $R_3 = 111 = (R_2 * 10 + 1)$
28+
29+
因為數值本身可能非常巨大,實作上只能追蹤「除以 k 的餘數」。
30+
31+
2. **避免整數溢位:只追蹤餘數即可**
32+
若我們令 $r_i$ 為 $R_i \bmod k$,則有以下遞推關係:
33+
34+
$$
35+
r_i = (r_{i-1} \times 10 + 1) \bmod k
36+
$$
37+
38+
只要有某個 $i$ 使得 $r_i = 0$,就代表長度為 $i$ 的全 1 數字可以被 $k$ 整除。
39+
40+
3. **模運算中的鴿籠原理(餘數有限)**
41+
所有可能的餘數只有 $0, 1, ..., k-1$ 共 $k$ 種。
42+
若我們從長度 1 一路試到長度 $k$ 都沒有看到餘數 `0`
43+
則必然已經出現「某個餘數重複」,之後只會在循環中打轉,不可能再得到新的餘數 `0`
44+
因此 **最長只需要檢查長度 1 到 $k$** ,超過就可以直接判定為不存在。
45+
46+
4. **2 與 5 的整除性特例**
47+
任何只由 `1` 組成的數字,其尾數必為 `1`
48+
因此不可能是 2 的倍數,也不可能是 5 的倍數。
49+
若 $k$ 含有質因數 2 或 5(亦即 $k \bmod 2 == 0$ 或 $k \bmod 5 == 0$),
50+
則不可能存在這樣的 $n$,直接回傳 `-1`
51+
52+
綜合以上,我們可以以模擬「逐步建立全 1 數字的餘數」的方式來找解,
53+
並利用 2/5 的特例與鴿籠原理控制迴圈上限。
54+
55+
## 解題步驟
56+
57+
### Step 1:特例判斷(必要條件)
58+
59+
`k` 可被 2 或 5 整除,repunit 不可能被其整除,因此立即返回 -1。
60+
61+
```typescript
62+
// 若能被 2 或 5 整除,repunit 不可能被 k 整除
63+
if (k % 2 === 0 || k % 5 === 0) {
64+
return -1;
65+
}
66+
```
67+
68+
### Step 2:初始化餘數並開始逐步構造 repunit
69+
70+
使用 `remainder` 表示當前 repunit 的餘數。
71+
之後從長度 1 一路嘗試到 k,套用公式更新餘數。
72+
73+
```typescript
74+
// 構造 repunit 時的餘數
75+
let remainder = 0;
76+
```
77+
78+
### Step 3:在迴圈中構造 repunit 的餘數並檢查是否可整除
79+
80+
每次迴圈將 repunit 往右擴增一位 `1`,並檢查餘數是否變為 0。
81+
若是,立刻回傳長度;若直到長度 k 都無法整除,返回 -1。
82+
83+
```typescript
84+
// 依鴿籠原理,最多只需搜尋到長度 k
85+
for (let length = 1; length <= k; length++) {
86+
// 更新 remainder = (remainder * 10 + 1) % k
87+
remainder = remainder * 10 + 1;
88+
remainder = remainder % k;
89+
90+
// 若餘數為 0,表示長度 length 即為答案
91+
if (remainder === 0) {
92+
return length;
93+
}
94+
}
95+
96+
return -1;
97+
```
98+
99+
## 時間複雜度
100+
101+
- 最多嘗試長度從 1 到 `k` 的所有候選長度,每次更新與檢查為常數時間;
102+
- 迴圈內僅進行簡單整數運算與取模操作。
103+
- 總時間複雜度為 $O(k)$。
104+
105+
> $O(k)$
106+
107+
## 空間複雜度
108+
109+
- 僅使用常數個變數(`remainder` 與計數變數 `length`);
110+
- 無額外與 `k` 成比例的資料結構。
111+
- 總空間複雜度為 $O(1)$。
112+
113+
> $O(1)$
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function smallestRepunitDivByK(k: number): number {
2+
// If divisible by 2 or 5, repunits cannot be divisible by k
3+
if (k % 2 === 0 || k % 5 === 0) {
4+
return -1;
5+
}
6+
7+
// Remainder when building repunits mod k
8+
let remainder = 0;
9+
10+
// Upper bound of search determined by pigeonhole principle
11+
for (let length = 1; length <= k; length++) {
12+
// Update remainder = (remainder * 10 + 1) % k
13+
remainder = remainder * 10 + 1;
14+
15+
// This modulo is unavoidable, but keeping it alone inside
16+
// the loop is the minimal possible cost
17+
remainder = remainder % k;
18+
19+
// When remainder hits zero, we found the answer
20+
if (remainder === 0) {
21+
return length;
22+
}
23+
}
24+
25+
return -1;
26+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function smallestRepunitDivByK(k: number): number {
2+
3+
}

0 commit comments

Comments
 (0)