Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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).
Original file line number Diff line number Diff line change
@@ -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`
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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)
}
})
}
}