3345. Smallest Divisible Digit Product I
題目 / Problem
中文: 給你兩個整數 n 和 t。請回傳一個「大於或等於 n」的最小數字,並且這個數字的各位數字乘積能被 t 整除。
English: You are given two integers n and t. Return the smallest number greater than or equal to n such that the product of its digits is divisible by t.
Constraints / 限制:
- 1 <= n <= 100
- 1 <= t <= 10
Worked example / 範例:
- Input: n = 15, t = 3
- Output: 16
- 解釋:從 15 開始往上找。15 的數字乘積是 1 × 5 = 5,5 不能被 3 整除。16 的數字乘積是 1 × 6 = 6,6 能被 3 整除,所以答案是 16。
名詞解釋 / Glossary
- 各位數字乘積 / digit product: 把一個數字的每一位數字相乘。例如 234 的數字乘積是
2 × 3 × 4 = 24。特別注意:只要有一位是 0,整個乘積就是 0。/ Multiply every individual digit of a number together. Note that a single 0 digit makes the whole product 0. - 整除 / divisible: 「a 能被 b 整除」代表
a除以b沒有餘數,也就是a % b == 0。/ "a is divisible by b" meansadivided bybleaves no remainder, i.e.a % b == 0. - 取餘數運算子
%/ modulo operator%: 回傳除法後的餘數。例如6 % 3 == 0、5 % 3 == 2。/ Returns the remainder after division. - 暴力枚舉 / brute force enumeration: 不用聰明技巧,直接一個一個把候選答案試過去,找到第一個符合條件的就回傳。/ Instead of a clever trick, just try each candidate one by one and return the first that works.
0是任何數的倍數 /0is a multiple of every number: 因為0 % t == 0對任何t都成立。這一點是本題的關鍵。/ Because0 % t == 0holds for anyt— a key fact here.
思路
中文:這題的資料範圍很小(n <= 100),而且提示也明講「最多只需要檢查 10 個數字」,所以最直接的暴力枚舉就是最好的解法。我們從 n 開始,一個一個往上試:對每個候選數字 x,先算出它的各位數字乘積,再檢查這個乘積能不能被 t 整除;只要找到第一個符合的,就立刻回傳。要算數字乘積,我們反覆用 x % 10 取出最右邊那一位,乘進累積變數,再用 x / 10(整數除法)把那一位去掉,直到 x 變成 0。為什麼這個做法一定會停下來、而且不用擔心找不到答案?因為只要某個數字包含 0 這一位(例如 10、20),它的數字乘積就是 0,而 0 能被任何 t 整除,所以答案一定存在且很快就會出現,最多往上找幾步就會碰到一個帶 0 的數字。
English: The input range is tiny (n <= 100) and the hint explicitly says we check at most 10 numbers, so plain brute-force enumeration is the right tool — no cleverness needed. Start at n and walk upward one integer at a time. For each candidate x, compute the product of its digits, then test whether that product is divisible by t; return the very first candidate that passes. To get the digit product, repeatedly take the last digit with x % 10, multiply it into a running accumulator, and drop that digit with integer division x / 10, looping until x reaches 0. Why is termination guaranteed? Any number containing a 0 digit (like 10 or 20) has digit product 0, and 0 is divisible by every t. So a valid answer always exists nearby and the loop stops quickly.
逐步走查 / Walkthrough
以第一個範例 n = 10, t = 2 為例 / Using the first example n = 10, t = 2:
我們從 x = 10 開始。先計算 10 的數字乘積 / We start at x = 10 and compute its digit product:
| 步驟 / step | x(剩餘數字 / remaining) |
x % 10(取出的位 / extracted digit) |
product(累積乘積 / running product) |
|---|---|---|---|
| 初始 / init | 10 | — | 1 |
| 迭代 1 / iter 1 | 10 | 0 | 1 × 0 = 0 |
| 迭代 2 / iter 2 | 1 | 1 | 0 × 1 = 0 |
| 結束 / done | 0 | — | 最終乘積 / final product = 0 |
- 現在檢查 / Now check:
product % t=0 % 2=0。餘數為 0,代表能被整除 / remainder is 0, so it is divisible. - 條件成立,立刻回傳
x = 10/ Condition holds, immediately returnx = 10. ✅
答案就是 10,跟預期輸出一致 / The answer is 10, matching the expected output.
Solution — C
// 演算法 / Algorithm:
// 從 n 開始逐一往上枚舉每個整數 x,計算 x 的各位數字乘積,
// 一旦該乘積能被 t 整除就回傳 x。因為帶 0 的數字乘積為 0(0 能被任何 t 整除),
// 答案一定存在且很快出現。
// Enumerate x upward from n, compute the digit product, return the first x
// whose product is divisible by t. A 0 digit guarantees an answer exists nearby.
int smallestNumber(int n, int t) {
// 從 n 開始,無限往上找,直到 return 為止
// Start at n and loop upward forever until we return.
for (int x = n; ; x++) {
long long product = 1; // 乘積初始化為 1(乘法單位元)/ init product to 1 (multiplicative identity)
int cur = x; // 用一個副本來拆解位數,保留原本的 x / a copy of x to peel digits from, keeping x intact
// 反覆取出最右邊一位並乘進 product,直到 cur 變成 0
// Repeatedly take the last digit and multiply it in, until cur becomes 0.
while (cur > 0) {
product *= cur % 10; // cur % 10 是最右一位;乘進累積乘積 / cur % 10 is the last digit; multiply it in
cur /= 10; // 整數除法去掉最右一位(如 123 -> 12)/ integer division drops the last digit (123 -> 12)
}
// 若數字乘積能被 t 整除(餘數為 0),x 就是答案
// If the digit product is divisible by t (remainder 0), x is the answer.
if (product % t == 0)
return x; // 回傳第一個符合的數字 / return the first matching number
}
}
Solution — C++
// 演算法 / Algorithm:
// 從 n 開始逐一往上枚舉每個整數 x,計算各位數字乘積,
// 回傳第一個乘積能被 t 整除的 x。帶 0 的數字保證答案存在。
// Enumerate x upward from n, compute digit product, return the first x whose
// product is divisible by t. A 0 digit guarantees an answer exists nearby.
class Solution {
public:
int smallestNumber(int n, int t) {
// 從 n 開始,一直往上枚舉,直到 return / enumerate upward from n until we return
for (int x = n; ; ++x) {
long long product = 1; // 乘積初始化為 1 / init product to 1 (multiplicative identity)
// 用副本 cur 逐位拆解 x,保留 x 本身
// Use a copy `cur` to peel digits, leaving x untouched.
for (int cur = x; cur > 0; cur /= 10) // cur /= 10 每輪去掉最右一位 / drop the last digit each round
product *= cur % 10; // cur % 10 是最右一位,乘進 product / last digit, multiplied in
// product % t == 0 代表能被整除;找到就回傳
// product % t == 0 means divisible; return once found.
if (product % t == 0)
return x; // 第一個符合條件的數字即為最小答案 / the first match is the smallest answer
}
}
};
複雜度 / Complexity
- Time: O(1) — 因為
n <= 100、t <= 10,最多往上檢查約 10 個數字,每個數字最多 3 位。這是一個由題目限制界定的常數量的工作,所以是常數時間。若以一般化角度看,設答案與n的距離為k、數字位數為d,則是O(k·d)。/ Withn <= 100, we check at most ~10 candidates, each with at most 3 digits — a constant amount of work bounded by the constraints. Generally it isO(k·d)wherekis the gap to the answer anddthe digit count. - Space: O(1) — 只用了
product、cur、x幾個變數,沒有配置任何額外的陣列或容器。/ Only a few scalar variables (product,cur,x); no arrays or containers allocated.
Pitfalls & Edge Cases
- 含 0 的數字乘積是 0 / A 0 digit makes the product 0: 例如
n = 10的乘積是1 × 0 = 0。因為0 % t == 0對任何t成立,這種數字必定符合條件——這正是範例 1 的答案,也是為什麼答案永遠存在。/ E.g.10gives product 0, and0 % t == 0for anyt, so it always qualifies — this is why an answer always exists. - product 要初始化成 1 而不是 0 / Initialize
productto 1, not 0: 乘法的單位元是 1;若初始化成 0,任何數的乘積都會被錯誤地變成 0。/ 1 is the multiplicative identity; starting at 0 would wrongly zero out every product. - 不要漏掉最左邊的位 / Don't drop the leading digit:
while (cur > 0)迴圈會一直跑到cur變 0,確保每一位都被乘到,不會少算最高位。/ Thewhile (cur > 0)loop runs untilcuris 0, ensuring every digit — including the highest — is included. t = 1的情況 / Whent = 1: 任何整數乘積都能被 1 整除(anything % 1 == 0),所以會直接回傳n本身。程式碼自然處理這點,不需特判。/ Every product is divisible by 1, sonitself is returned; the code handles this without a special case.- 不要用
int累積乘積怕溢位(本題不會)/ Overflow: 本題數字很小不會溢位,但我們仍用long long存product作為好習慣,避免在更大範圍的變體題中出錯。/ Values here are tiny sointwould suffice, but we uselong longforproductas a safe habit for larger variants. - 回傳值別搞混 / Return-value confusion: 要回傳的是候選數字
x本身,而不是它的數字乘積product。/ Return the candidatex, not its digit productproduct.