diff --git a/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/analysis_daily_20260708.md b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/analysis_daily_20260708.md new file mode 100644 index 0000000..4261105 --- /dev/null +++ b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/analysis_daily_20260708.md @@ -0,0 +1,78 @@ +# 3756. Concatenate Non-Zero Digits and Multiply by Sum II + +[LeetCode Link](https://leetcode.com/problems/concatenate-non-zero-digits-and-multiply-by-sum-ii/) + +Difficulty: Medium +Topics: Math, String, Prefix Sum + +Acceptance Rate: 31.3% + +## Hints + +### Hint 1 + +There can be up to `10^5` queries over a string of length up to `10^5`. Rebuilding the number for every query would be `O(m)` per query and `O(m * q)` overall, which is far too slow. Whenever you see "answer many range queries fast," think about precomputing prefix information so each query becomes `O(1)`. The tricky part here is that the quantity you care about — a *concatenated* integer — does not obviously decompose into a simple prefix sum. Try to express it as one anyway. + +### Hint 2 + +The answer is `x * sum`, where `sum` is just the sum of the non-zero digits in the range. That half is easy: keep a prefix sum of digit values and subtract. The hard half is `x`, the integer formed by gluing the non-zero digits together. Think about what each digit contributes to the final value of `x`. A non-zero digit `d` sitting `k` non-zero-digits before the end of the range contributes `d * 10^k`. Notice that `k` depends only on how many non-zero digits come *after* it — which is itself a prefix-countable quantity. + +### Hint 3 + +Let `nz[i]` be the count of non-zero digits in `s[0..i-1]`. For a query `[l, r]`, a non-zero digit at position `j` contributes `d_j * 10^(nz[r+1] - nz[j+1])`. Factor out the range-dependent exponent: + +``` +x = 10^(nz[r+1]) * sum_{j in [l, r], s[j] != 0} d_j * 10^(-nz[j+1]) +``` + +The inner sum no longer depends on `r`, so it *is* a prefix sum. Precompute `pref[i] = sum of d_j * inverse10^(nz[j+1])` for all non-zero `j < i` under the modulus (using the modular inverse of 10). Each query then costs a single subtraction and one multiplication by `10^(nz[r+1])`. + +## Approach + +We work entirely modulo `p = 10^9 + 7`. Two independent quantities are needed per query: the concatenated integer `x` and the digit sum `sum`. + +**Digit sum.** Zeros contribute nothing to the sum, so `sum` is simply the sum of the non-zero digits in the range. Maintain a prefix array `dsum[i]` = sum of non-zero digit values in `s[0..i-1]`. Then `sum = dsum[r+1] - dsum[l]`. + +**The concatenated integer `x`.** When we glue the non-zero digits `d_{j1} d_{j2} ... d_{jc}` of the range together (in original order), the value is + +``` +x = d_{j1} * 10^(c-1) + d_{j2} * 10^(c-2) + ... + d_{jc} * 10^0 +``` + +where `c` is how many non-zero digits the range has. The exponent on a given digit equals the number of non-zero digits that follow it inside the range. + +Define `nz[i]` = number of non-zero digits in `s[0..i-1]`. For a non-zero digit at position `j`, the number of non-zero digits after it within `[l, r]` is `nz[r+1] - nz[j+1]`. Hence + +``` +x = sum_j d_j * 10^(nz[r+1] - nz[j+1]) + = 10^(nz[r+1]) * sum_j ( d_j * inv10^(nz[j+1]) ) +``` + +where `inv10` is the modular inverse of 10. The bracketed term is range-independent, so we precompute the prefix sum + +``` +pref[i] = sum over non-zero positions j < i of d_j * inv10^(nz[j+1]) (mod p) +``` + +For a query, `x = 10^(nz[r+1]) * (pref[r+1] - pref[l]) (mod p)`. + +**Putting it together.** Precompute `pow10[]`, `invPow10[]`, `nz[]`, `pref[]`, and `dsum[]` in a single `O(m)` pass. Each query is answered in `O(1)`: + +1. `cnt = nz[r+1] - nz[l]`. If `cnt == 0`, there are no non-zero digits, so `x = 0` and the answer is `0`. +2. Otherwise `x = pow10[nz[r+1]] * ((pref[r+1] - pref[l]) mod p)` and `sum = dsum[r+1] - dsum[l]`. +3. Answer is `x * sum mod p`. + +*Worked example* (`s = "10203004"`, query `[0, 7]`): the non-zero digits are `1, 2, 3, 4` at positions `0, 2, 4, 7`. Their exponents (non-zero digits after them) are `3, 2, 1, 0`, giving `1000 + 200 + 30 + 4 = 1234`. The digit sum is `10`, so the answer is `12340`, matching the expected output. + +## Complexity Analysis + +Time Complexity: O(m + q), where `m = len(s)` and `q = len(queries)`. Precomputation is a single linear pass (the one modular exponentiation for `inv10` is `O(log p)`); each query is answered in constant time. +Space Complexity: O(m) for the prefix and power tables. + +## Edge Cases + +- **No non-zero digits in the range** (e.g. `"000"`): `x = 0`, so the answer must be `0` — guard on `cnt == 0` to avoid multiplying by an empty prefix difference. +- **Trailing zeros** (e.g. `"300"` -> `x = 3`): zeros are simply skipped; the exponent bookkeeping via `nz` handles this automatically because zeros never increment the non-zero counter. +- **Single-character range** (`l == r`): must work whether that character is zero (answer `0`) or non-zero (answer `d * d`). +- **Modular subtraction underflow**: `pref[r+1] - pref[l]` can be negative under the modulus; add `p` before taking the final modulus. +- **Large results**: `x` can be an integer with up to `10^5` digits, so it must be kept modulo `p` throughout — never build the actual number. Also confirm that `x * sum` stays within `int64` (both factors are below `p`, so the product fits). diff --git a/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/problem.md b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/problem.md new file mode 100644 index 0000000..29f53de --- /dev/null +++ b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/problem.md @@ -0,0 +1,102 @@ +--- +number: "3756" +frontend_id: "3756" +title: "Concatenate Non-Zero Digits and Multiply by Sum II" +slug: "concatenate-non-zero-digits-and-multiply-by-sum-ii" +difficulty: "Medium" +topics: + - "Math" + - "String" + - "Prefix Sum" +acceptance_rate: 3132.1 +is_premium: false +created_at: "2026-07-08T03:52:46.269557+00:00" +fetched_at: "2026-07-08T03:52:46.269557+00:00" +link: "https://leetcode.com/problems/concatenate-non-zero-digits-and-multiply-by-sum-ii/" +date: "2026-07-08" +--- + +# 3756. Concatenate Non-Zero Digits and Multiply by Sum II + +You are given a string `s` of length `m` consisting of digits. You are also given a 2D integer array `queries`, where `queries[i] = [li, ri]`. + +For each `queries[i]`, extract the **substring** `s[li..ri]`. Then, perform the following: + + * Form a new integer `x` by concatenating all the **non-zero digits** from the substring in their original order. If there are no non-zero digits, `x = 0`. + * Let `sum` be the **sum of digits** in `x`. The answer is `x * sum`. + + + +Return an array of integers `answer` where `answer[i]` is the answer to the `ith` query. + +Since the answers may be very large, return them **modulo** `109 + 7`. + + + +**Example 1:** + +**Input:** s = "10203004", queries = [[0,7],[1,3],[4,6]] + +**Output:** [12340, 4, 9] + +**Explanation:** + + * `s[0..7] = "10203004"` + * `x = 1234` + * `sum = 1 + 2 + 3 + 4 = 10` + * Therefore, answer is `1234 * 10 = 12340`. + * `s[1..3] = "020"` + * `x = 2` + * `sum = 2` + * Therefore, the answer is `2 * 2 = 4`. + * `s[4..6] = "300"` + * `x = 3` + * `sum = 3` + * Therefore, the answer is `3 * 3 = 9`. + + + +**Example 2:** + +**Input:** s = "1000", queries = [[0,3],[1,1]] + +**Output:** [1, 0] + +**Explanation:** + + * `s[0..3] = "1000"` + * `x = 1` + * `sum = 1` + * Therefore, the answer is `1 * 1 = 1`. + * `s[1..1] = "0"` + * `x = 0` + * `sum = 0` + * Therefore, the answer is `0 * 0 = 0`. + + + +**Example 3:** + +**Input:** s = "9876543210", queries = [[0,9]] + +**Output:** [444444137] + +**Explanation:** + + * `s[0..9] = "9876543210"` + * `x = 987654321` + * `sum = 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 = 45` + * Therefore, the answer is `987654321 * 45 = 44444444445`. + * We return `44444444445 modulo (109 + 7) = 444444137`. + + + + + +**Constraints:** + + * `1 <= m == s.length <= 105` + * `s` consists of digits only. + * `1 <= queries.length <= 105` + * `queries[i] = [li, ri]` + * `0 <= li <= ri < m` diff --git a/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708.go b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708.go new file mode 100644 index 0000000..5e6200d --- /dev/null +++ b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708.go @@ -0,0 +1,77 @@ +package main + +// 3756. Concatenate Non-Zero Digits and Multiply by Sum II +// +// For each query [l, r] we need x*sum (mod 1e9+7), where x is the integer +// formed by concatenating the non-zero digits of s[l..r] and sum is the sum +// of those digits. +// +// Key insight: a non-zero digit at position j contributes +// d_j * 10^(number of non-zero digits after j within the range). +// Letting nz[i] be the count of non-zero digits in s[0..i-1], that exponent +// is nz[r+1] - nz[j+1]. Factoring out the range-dependent part: +// x = 10^(nz[r+1]) * sum_j ( d_j * inv10^(nz[j+1]) ) +// The inner sum is a prefix sum (pref), so every query is answered in O(1) +// after an O(m) precomputation. The digit sum is a plain prefix sum (dsum). + +func processQueries(s string, queries [][]int) []int { + const mod = 1_000_000_007 + m := len(s) + + // Powers of 10 and their modular inverses, indexed by exponent. + pow10 := make([]int64, m+1) + invPow10 := make([]int64, m+1) + pow10[0] = 1 + for i := 1; i <= m; i++ { + pow10[i] = pow10[i-1] * 10 % mod + } + inv10 := modpow(10, mod-2, mod) + invPow10[0] = 1 + for i := 1; i <= m; i++ { + invPow10[i] = invPow10[i-1] * inv10 % mod + } + + // Prefix arrays over s[0..i-1]. + nz := make([]int, m+1) // count of non-zero digits + pref := make([]int64, m+1) // sum of d_j * inv10^(nz[j+1]) for non-zero j + dsum := make([]int64, m+1) // sum of non-zero digit values + for i := 0; i < m; i++ { + d := int64(s[i] - '0') + nz[i+1] = nz[i] + pref[i+1] = pref[i] + dsum[i+1] = dsum[i] + if d != 0 { + nz[i+1]++ + pref[i+1] = (pref[i+1] + d*invPow10[nz[i+1]]) % mod + dsum[i+1] += d + } + } + + ans := make([]int, len(queries)) + for qi, q := range queries { + l, r := q[0], q[1] + if nz[r+1]-nz[l] == 0 { + ans[qi] = 0 + continue + } + sumContrib := ((pref[r+1]-pref[l])%mod + mod) % mod + x := pow10[nz[r+1]] * sumContrib % mod + sum := (dsum[r+1] - dsum[l]) % mod + ans[qi] = int(x * sum % mod) + } + return ans +} + +// modpow computes base^exp mod m using fast exponentiation. +func modpow(base, exp, m int64) int64 { + result := int64(1) + base %= m + for exp > 0 { + if exp&1 == 1 { + result = result * base % m + } + base = base * base % m + exp >>= 1 + } + return result +} diff --git a/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708_test.go b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708_test.go new file mode 100644 index 0000000..506e036 --- /dev/null +++ b/problems/3756-concatenate-non-zero-digits-and-multiply-by-sum-ii/solution_daily_20260708_test.go @@ -0,0 +1,61 @@ +package main + +import ( + "reflect" + "testing" +) + +func TestSolution(t *testing.T) { + tests := []struct { + name string + s string + queries [][]int + expected []int + }{ + { + name: "example 1: mixed digits with interspersed zeros", + s: "10203004", + queries: [][]int{{0, 7}, {1, 3}, {4, 6}}, + expected: []int{12340, 4, 9}, + }, + { + name: "example 2: trailing zeros and single zero", + s: "1000", + queries: [][]int{{0, 3}, {1, 1}}, + expected: []int{1, 0}, + }, + { + name: "example 3: modulo wrap on large product", + s: "9876543210", + queries: [][]int{{0, 9}}, + expected: []int{444444137}, + }, + { + name: "edge case: all zeros yields zero", + s: "0000", + queries: [][]int{{0, 3}, {2, 2}}, + expected: []int{0, 0}, + }, + { + name: "edge case: single non-zero digit", + s: "5", + queries: [][]int{{0, 0}}, + expected: []int{25}, // x = 5, sum = 5, 5*5 = 25 + }, + { + name: "edge case: contiguous non-zero digits and subranges", + s: "12345", + queries: [][]int{{0, 4}, {1, 3}, {2, 2}}, + expected: []int{185175, 2106, 9}, // 12345*15, 234*9, 3*3 + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := processQueries(tt.s, tt.queries) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("processQueries(%q, %v) = %v, want %v", tt.s, tt.queries, result, tt.expected) + } + }) + } +}