diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md b/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md index 4d89e50ccc1d1..5da5233e13a4e 100644 --- a/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/README.md @@ -112,32 +112,352 @@ tags: -### 方法一 +### 方法一:二分查找 + 位运算 + +连续的正整数数字对应的强整数数组连接得到数组 $\textit{big\_nums}$,题目需要我们求出对于每个查询 $[\textit{left}, \textit{right}, \textit{mod}]$,子数组 $\textit{big\_nums}[\textit{left}..\textit{right}]$ 的乘积对 $\textit{mod}$ 取模的结果。由于子数组每个元素都是 $2$ 的幂,这等价于求子数组的幂次之和 $\textit{power}$,然后计算 $2^{\textit{power}} \bmod \textit{mod}$。例如,对于子数组 $[1, 4, 8]$,即 $[2^0, 2^2, 2^3]$,其幂次之和为 $0 + 2 + 3 = 5$,所以 $2^5 \bmod \textit{mod}$ 就是我们要求的结果。 + +因此,我们不妨将 $\textit{big\_nums}$ 转换为幂次数组,即对于子数组 $[1, 4, 8]$,我们将其转换为 $[0, 2, 3]$。这样,问题转换为求幂次数组的子数组之和,即 $\textit{power} = \textit{f}(\textit{right} + 1) - \textit{f}(\textit{left})$,其中 $\textit{f}(i)$ 表示 $\textit{big\_nums}[0..i)$ 的幂次之和,也即是前缀和。 + +接下来,就是根据下标 $i$ 计算 $\textit{f}(i)$ 的值。我们可以使用二分查找的方法,先找到强数组长度和小于 $i$ 的最大数字,然后再计算剩下的数字的幂次之和。 + +我们根据题目描述,列出数字 $0..14$ 的强整数: + +| $\textit{nums}$ | 8($2^3$) | 4($2^2$) | 2($2^1$) | ($2^0$) | +| --------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| 0 | 0 | 0 | 0 | 0 | +| 1 | 0 | 0 | 0 | 1 | +| 2 | 0 | 0 | 1 | 0 | +| 3 | 0 | 0 | 1 | 1 | +| 4 | 0 | 1 | 0 | 0 | +| 5 | 0 | 1 | 0 | 1 | +| 6 | 0 | 1 | 1 | 0 | +| 7 | 0 | 1 | 1 | 1 | +| 8 | 1 | 0 | 0 | 0 | +| 9 | 1 | 0 | 0 | 1 | +| 10 | 1 | 0 | 1 | 0 | +| 11 | 1 | 0 | 1 | 1 | +| 12 | 1 | 1 | 0 | 0 | +| 13 | 1 | 1 | 0 | 1 | +| 14 | 1 | 1 | 1 | 0 | + +将数字按照 $[2^i, 2^{i+1}-1]$ 的区间划分为不同的颜色,可以发现,区间 $[2^i, 2^{i+1}-1]$ 的数字,相当于在区间 $[0, 2^i-1]$ 的数字基础上,每个数字加上 $2^i$。我们可以根据这个规律,计算出 $\textit{big\_nums}$ 的前 $i$ 组的所有数字的强数组个数之和 $\textit{cnt}[i]$ 和幂次之和 $\textit{s}[i]$。 + +接下来,对于任何数字,我们考虑如何计算其强数组的个数和幂次之和。我们可以通过二进制的方式,从最高位开始,诸位计算。例如,对于数字 $13 = 2^3 + 2^2 + 2^0$,前 $2^3$ 个数字的结果可以由 $textit{cnt}[3]$ 和 $\textit{s}[3]$ 计算得到,而剩下的 $[2^3, 13]$ 的结果,相当于给 $[0, 13-2^3]$ 的所有数字,即 $[0, 5]$ 的所有数字的强数组增加 $3$,问题转换为计算 $[0, 5]$ 的所有数字的强数组的个数和幂次之和。这样,我们可以计算出任意数字的强数组的个数和幂次之和。 + +最后,我们可以根据 $\textit{power}$ 的值,利用快速幂的方法,计算出 $2^{\textit{power}} \bmod \textit{mod}$ 的结果。 + +时间复杂度 $O(q \times \log M)$,空间复杂度 $(\log M)$。其中 $q$ 为查询的个数,而 $M$ 为数字的上界,本题中 $M \le 10^{15}$。 #### Python3 ```python - +m = 50 +cnt = [0] * (m + 1) +s = [0] * (m + 1) +p = 1 +for i in range(1, m + 1): + cnt[i] = cnt[i - 1] * 2 + p + s[i] = s[i - 1] * 2 + p * (i - 1) + p *= 2 + + +def num_idx_and_sum(x: int) -> tuple: + idx = 0 + total_sum = 0 + while x: + i = x.bit_length() - 1 + idx += cnt[i] + total_sum += s[i] + x -= 1 << i + total_sum += (x + 1) * i + idx += x + 1 + return (idx, total_sum) + + +def f(i: int) -> int: + l, r = 0, 1 << m + while l < r: + mid = (l + r + 1) >> 1 + idx, _ = num_idx_and_sum(mid) + if idx < i: + l = mid + else: + r = mid - 1 + + total_sum = 0 + idx, total_sum = num_idx_and_sum(l) + i -= idx + x = l + 1 + for _ in range(i): + y = x & -x + total_sum += y.bit_length() - 1 + x -= y + return total_sum + + +class Solution: + def findProductsOfElements(self, queries: List[List[int]]) -> List[int]: + return [pow(2, f(right + 1) - f(left), mod) for left, right, mod in queries] ``` #### Java ```java - +class Solution { + private static final int M = 50; + private static final long[] cnt = new long[M + 1]; + private static final long[] s = new long[M + 1]; + + static { + long p = 1; + for (int i = 1; i <= M; i++) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + } + + private static long[] numIdxAndSum(long x) { + long idx = 0; + long totalSum = 0; + while (x > 0) { + int i = Long.SIZE - Long.numberOfLeadingZeros(x) - 1; + idx += cnt[i]; + totalSum += s[i]; + x -= 1L << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return new long[] {idx, totalSum}; + } + + private static long f(long i) { + long l = 0; + long r = 1L << M; + while (l < r) { + long mid = (l + r + 1) >> 1; + long[] idxAndSum = numIdxAndSum(mid); + long idx = idxAndSum[0]; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + long[] idxAndSum = numIdxAndSum(l); + long totalSum = idxAndSum[1]; + long idx = idxAndSum[0]; + i -= idx; + long x = l + 1; + for (int j = 0; j < i; j++) { + long y = x & -x; + totalSum += Long.numberOfTrailingZeros(y); + x -= y; + } + return totalSum; + } + + public int[] findProductsOfElements(long[][] queries) { + int n = queries.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + long left = queries[i][0]; + long right = queries[i][1]; + long mod = queries[i][2]; + long power = f(right + 1) - f(left); + ans[i] = qpow(2, power, mod); + } + return ans; + } + + private int qpow(long a, long n, long mod) { + long ans = 1 % mod; + for (; n > 0; n >>= 1) { + if ((n & 1) == 1) { + ans = ans * a % mod; + } + a = a * a % mod; + } + return (int) ans; + } +} ``` #### C++ ```cpp - +using ll = long long; +const int m = 50; +ll cnt[m + 1]; +ll s[m + 1]; +ll p = 1; + +auto init = [] { + cnt[0] = 0; + s[0] = 0; + for (int i = 1; i <= m; ++i) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + return 0; +}(); + +pair numIdxAndSum(ll x) { + ll idx = 0; + ll totalSum = 0; + while (x > 0) { + int i = 63 - __builtin_clzll(x); + idx += cnt[i]; + totalSum += s[i]; + x -= 1LL << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return make_pair(idx, totalSum); +} + +ll f(ll i) { + ll l = 0; + ll r = 1LL << m; + while (l < r) { + ll mid = (l + r + 1) >> 1; + auto idxAndSum = numIdxAndSum(mid); + ll idx = idxAndSum.first; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + auto idxAndSum = numIdxAndSum(l); + ll totalSum = idxAndSum.second; + ll idx = idxAndSum.first; + i -= idx; + ll x = l + 1; + for (int j = 0; j < i; ++j) { + ll y = x & -x; + totalSum += __builtin_ctzll(y); + x -= y; + } + return totalSum; +} + +ll qpow(ll a, ll n, ll mod) { + ll ans = 1 % mod; + a = a % mod; + while (n > 0) { + if (n & 1) { + ans = ans * a % mod; + } + a = a * a % mod; + n >>= 1; + } + return ans; +} + +class Solution { +public: + vector findProductsOfElements(vector>& queries) { + int n = queries.size(); + vector ans(n); + for (int i = 0; i < n; ++i) { + ll left = queries[i][0]; + ll right = queries[i][1]; + ll mod = queries[i][2]; + ll power = f(right + 1) - f(left); + if (power < 0) { + power += mod; + } + ans[i] = static_cast(qpow(2, power, mod)); + } + return ans; + } +}; ``` #### Go ```go - +const m = 50 + +var cnt [m + 1]int64 +var s [m + 1]int64 +var p int64 = 1 + +func init() { + cnt[0] = 0 + s[0] = 0 + for i := 1; i <= m; i++ { + cnt[i] = cnt[i-1]*2 + p + s[i] = s[i-1]*2 + p*(int64(i)-1) + p *= 2 + } +} + +func numIdxAndSum(x int64) (int64, int64) { + var idx, totalSum int64 + for x > 0 { + i := 63 - bits.LeadingZeros64(uint64(x)) + idx += cnt[i] + totalSum += s[i] + x -= 1 << i + totalSum += (x + 1) * int64(i) + idx += x + 1 + } + return idx, totalSum +} + +func f(i int64) int64 { + l, r := int64(0), int64(1)<> 1 + idx, _ := numIdxAndSum(mid) + if idx < i { + l = mid + } else { + r = mid - 1 + } + } + + _, totalSum := numIdxAndSum(l) + idx, _ := numIdxAndSum(l) + i -= idx + x := l + 1 + for j := int64(0); j < i; j++ { + y := x & -x + totalSum += int64(bits.TrailingZeros64(uint64(y))) + x -= y + } + return totalSum +} + +func qpow(a, n, mod int64) int64 { + ans := int64(1) % mod + a = a % mod + for n > 0 { + if n&1 == 1 { + ans = (ans * a) % mod + } + a = (a * a) % mod + n >>= 1 + } + return ans +} + +func findProductsOfElements(queries [][]int64) []int { + ans := make([]int, len(queries)) + for i, q := range queries { + left, right, mod := q[0], q[1], q[2] + power := f(right+1) - f(left) + ans[i] = int(qpow(2, power, mod)) + } + return ans +} ``` diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md b/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md index 381aec84bfd43..14898accd95fc 100644 --- a/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/README_EN.md @@ -110,32 +110,352 @@ tags: -### Solution 1 +### Solution 1: Binary Search + Bit Manipulation + +The continuous positive integer numbers correspond to the strong integer array, forming the array $\textit{big\_nums}$. The problem requires us to find the result of the product of the subarray $\textit{big\_nums}[\textit{left}..\textit{right}]$ modulo $\textit{mod}$ for each query $[\textit{left}, \textit{right}, \textit{mod}]$. Since each element of the subarray is a power of 2, this is equivalent to finding the sum of the powers $\textit{power}$ of the subarray, and then calculating $2^{\textit{power}} \bmod \textit{mod}$. For example, for the subarray $[1, 4, 8]$, i.e., $[2^0, 2^2, 2^3]$, the sum of the powers is $0 + 2 + 3 = 5$, so $2^5 \bmod \textit{mod}$ is the result we need. + +Therefore, we can convert $\textit{big\_nums}$ into an array of powers. For example, for the subarray $[1, 4, 8]$, we convert it to $[0, 2, 3]$. Thus, the problem is transformed into finding the sum of the subarray of powers, i.e., $\textit{power} = \textit{f}(\textit{right} + 1) - \textit{f}(\textit{left})$, where $\textit{f}(i)$ represents the sum of the powers of $\textit{big\_nums}[0..i)$, which is the prefix sum. + +Next, we calculate the value of $\textit{f}(i)$ based on the index $i$. We can use binary search to find the largest number whose strong array length is less than $i$, and then calculate the sum of the powers of the remaining numbers. + +According to the problem description, we list the strong integers for numbers $0..14$: + +| $\textit{nums}$ | 8($2^3$) | 4($2^2$) | 2($2^1$) | ($2^0$) | +| --------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| 0 | 0 | 0 | 0 | 0 | +| 1 | 0 | 0 | 0 | 1 | +| 2 | 0 | 0 | 1 | 0 | +| 3 | 0 | 0 | 1 | 1 | +| 4 | 0 | 1 | 0 | 0 | +| 5 | 0 | 1 | 0 | 1 | +| 6 | 0 | 1 | 1 | 0 | +| 7 | 0 | 1 | 1 | 1 | +| 8 | 1 | 0 | 0 | 0 | +| 9 | 1 | 0 | 0 | 1 | +| 10 | 1 | 0 | 1 | 0 | +| 11 | 1 | 0 | 1 | 1 | +| 12 | 1 | 1 | 0 | 0 | +| 13 | 1 | 1 | 0 | 1 | +| 14 | 1 | 1 | 1 | 0 | + +By dividing the numbers into different colors according to the interval $[2^i, 2^{i+1}-1]$, we can see that the numbers in the interval $[2^i, 2^{i+1}-1]$ are equivalent to adding $2^i$ to each number in the interval $[0, 2^i-1]$. Based on this pattern, we can calculate the total number of strong arrays $\textit{cnt}[i]$ and the sum of powers $\textit{s}[i]$ for the first $i$ groups of numbers in $\textit{big\_nums}$. + +Next, for any number, we consider how to calculate the number of strong arrays and the sum of powers. We can use the binary method, calculating from the highest bit. For example, for the number $13 = 2^3 + 2^2 + 2^0$, the result of the first $2^3$ numbers can be obtained from $\textit{cnt}[3]$ and $\textit{s}[3]$, and the result of the remaining $[2^3, 13]$ is equivalent to adding $3$ to all numbers in $[0, 13-2^3]$, i.e., $[0, 5]$. The problem is transformed into calculating the number of strong arrays and the sum of powers for $[0, 5]$. In this way, we can calculate the number of strong arrays and the sum of powers for any number. + +Finally, based on the value of $\textit{power}$, we use the fast exponentiation method to calculate the result of $2^{\textit{power}} \bmod \textit{mod}$. + +The time complexity is $O(q \times \log M)$, and the space complexity is $O(\log M)$. Here, $q$ is the number of queries, and $M$ is the upper bound of the number, with $M \le 10^{15}$ in this problem. #### Python3 ```python - +m = 50 +cnt = [0] * (m + 1) +s = [0] * (m + 1) +p = 1 +for i in range(1, m + 1): + cnt[i] = cnt[i - 1] * 2 + p + s[i] = s[i - 1] * 2 + p * (i - 1) + p *= 2 + + +def num_idx_and_sum(x: int) -> tuple: + idx = 0 + total_sum = 0 + while x: + i = x.bit_length() - 1 + idx += cnt[i] + total_sum += s[i] + x -= 1 << i + total_sum += (x + 1) * i + idx += x + 1 + return (idx, total_sum) + + +def f(i: int) -> int: + l, r = 0, 1 << m + while l < r: + mid = (l + r + 1) >> 1 + idx, _ = num_idx_and_sum(mid) + if idx < i: + l = mid + else: + r = mid - 1 + + total_sum = 0 + idx, total_sum = num_idx_and_sum(l) + i -= idx + x = l + 1 + for _ in range(i): + y = x & -x + total_sum += y.bit_length() - 1 + x -= y + return total_sum + + +class Solution: + def findProductsOfElements(self, queries: List[List[int]]) -> List[int]: + return [pow(2, f(right + 1) - f(left), mod) for left, right, mod in queries] ``` #### Java ```java - +class Solution { + private static final int M = 50; + private static final long[] cnt = new long[M + 1]; + private static final long[] s = new long[M + 1]; + + static { + long p = 1; + for (int i = 1; i <= M; i++) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + } + + private static long[] numIdxAndSum(long x) { + long idx = 0; + long totalSum = 0; + while (x > 0) { + int i = Long.SIZE - Long.numberOfLeadingZeros(x) - 1; + idx += cnt[i]; + totalSum += s[i]; + x -= 1L << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return new long[] {idx, totalSum}; + } + + private static long f(long i) { + long l = 0; + long r = 1L << M; + while (l < r) { + long mid = (l + r + 1) >> 1; + long[] idxAndSum = numIdxAndSum(mid); + long idx = idxAndSum[0]; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + long[] idxAndSum = numIdxAndSum(l); + long totalSum = idxAndSum[1]; + long idx = idxAndSum[0]; + i -= idx; + long x = l + 1; + for (int j = 0; j < i; j++) { + long y = x & -x; + totalSum += Long.numberOfTrailingZeros(y); + x -= y; + } + return totalSum; + } + + public int[] findProductsOfElements(long[][] queries) { + int n = queries.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + long left = queries[i][0]; + long right = queries[i][1]; + long mod = queries[i][2]; + long power = f(right + 1) - f(left); + ans[i] = qpow(2, power, mod); + } + return ans; + } + + private int qpow(long a, long n, long mod) { + long ans = 1 % mod; + for (; n > 0; n >>= 1) { + if ((n & 1) == 1) { + ans = ans * a % mod; + } + a = a * a % mod; + } + return (int) ans; + } +} ``` #### C++ ```cpp - +using ll = long long; +const int m = 50; +ll cnt[m + 1]; +ll s[m + 1]; +ll p = 1; + +auto init = [] { + cnt[0] = 0; + s[0] = 0; + for (int i = 1; i <= m; ++i) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + return 0; +}(); + +pair numIdxAndSum(ll x) { + ll idx = 0; + ll totalSum = 0; + while (x > 0) { + int i = 63 - __builtin_clzll(x); + idx += cnt[i]; + totalSum += s[i]; + x -= 1LL << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return make_pair(idx, totalSum); +} + +ll f(ll i) { + ll l = 0; + ll r = 1LL << m; + while (l < r) { + ll mid = (l + r + 1) >> 1; + auto idxAndSum = numIdxAndSum(mid); + ll idx = idxAndSum.first; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + auto idxAndSum = numIdxAndSum(l); + ll totalSum = idxAndSum.second; + ll idx = idxAndSum.first; + i -= idx; + ll x = l + 1; + for (int j = 0; j < i; ++j) { + ll y = x & -x; + totalSum += __builtin_ctzll(y); + x -= y; + } + return totalSum; +} + +ll qpow(ll a, ll n, ll mod) { + ll ans = 1 % mod; + a = a % mod; + while (n > 0) { + if (n & 1) { + ans = ans * a % mod; + } + a = a * a % mod; + n >>= 1; + } + return ans; +} + +class Solution { +public: + vector findProductsOfElements(vector>& queries) { + int n = queries.size(); + vector ans(n); + for (int i = 0; i < n; ++i) { + ll left = queries[i][0]; + ll right = queries[i][1]; + ll mod = queries[i][2]; + ll power = f(right + 1) - f(left); + if (power < 0) { + power += mod; + } + ans[i] = static_cast(qpow(2, power, mod)); + } + return ans; + } +}; ``` #### Go ```go - +const m = 50 + +var cnt [m + 1]int64 +var s [m + 1]int64 +var p int64 = 1 + +func init() { + cnt[0] = 0 + s[0] = 0 + for i := 1; i <= m; i++ { + cnt[i] = cnt[i-1]*2 + p + s[i] = s[i-1]*2 + p*(int64(i)-1) + p *= 2 + } +} + +func numIdxAndSum(x int64) (int64, int64) { + var idx, totalSum int64 + for x > 0 { + i := 63 - bits.LeadingZeros64(uint64(x)) + idx += cnt[i] + totalSum += s[i] + x -= 1 << i + totalSum += (x + 1) * int64(i) + idx += x + 1 + } + return idx, totalSum +} + +func f(i int64) int64 { + l, r := int64(0), int64(1)<> 1 + idx, _ := numIdxAndSum(mid) + if idx < i { + l = mid + } else { + r = mid - 1 + } + } + + _, totalSum := numIdxAndSum(l) + idx, _ := numIdxAndSum(l) + i -= idx + x := l + 1 + for j := int64(0); j < i; j++ { + y := x & -x + totalSum += int64(bits.TrailingZeros64(uint64(y))) + x -= y + } + return totalSum +} + +func qpow(a, n, mod int64) int64 { + ans := int64(1) % mod + a = a % mod + for n > 0 { + if n&1 == 1 { + ans = (ans * a) % mod + } + a = (a * a) % mod + n >>= 1 + } + return ans +} + +func findProductsOfElements(queries [][]int64) []int { + ans := make([]int, len(queries)) + for i, q := range queries { + left, right, mod := q[0], q[1], q[2] + power := f(right+1) - f(left) + ans[i] = int(qpow(2, power, mod)) + } + return ans +} ``` diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.cpp b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.cpp new file mode 100644 index 0000000000000..f4f9c758d8d77 --- /dev/null +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.cpp @@ -0,0 +1,86 @@ +using ll = long long; +const int m = 50; +ll cnt[m + 1]; +ll s[m + 1]; +ll p = 1; + +auto init = [] { + cnt[0] = 0; + s[0] = 0; + for (int i = 1; i <= m; ++i) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + return 0; +}(); + +pair numIdxAndSum(ll x) { + ll idx = 0; + ll totalSum = 0; + while (x > 0) { + int i = 63 - __builtin_clzll(x); + idx += cnt[i]; + totalSum += s[i]; + x -= 1LL << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return make_pair(idx, totalSum); +} + +ll f(ll i) { + ll l = 0; + ll r = 1LL << m; + while (l < r) { + ll mid = (l + r + 1) >> 1; + auto idxAndSum = numIdxAndSum(mid); + ll idx = idxAndSum.first; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + auto idxAndSum = numIdxAndSum(l); + ll totalSum = idxAndSum.second; + ll idx = idxAndSum.first; + i -= idx; + ll x = l + 1; + for (int j = 0; j < i; ++j) { + ll y = x & -x; + totalSum += __builtin_ctzll(y); + x -= y; + } + return totalSum; +} + +ll qpow(ll a, ll n, ll mod) { + ll ans = 1 % mod; + a = a % mod; + while (n > 0) { + if (n & 1) { + ans = ans * a % mod; + } + a = a * a % mod; + n >>= 1; + } + return ans; +} + +class Solution { +public: + vector findProductsOfElements(vector>& queries) { + int n = queries.size(); + vector ans(n); + for (int i = 0; i < n; ++i) { + ll left = queries[i][0]; + ll right = queries[i][1]; + ll mod = queries[i][2]; + ll power = f(right + 1) - f(left); + ans[i] = static_cast(qpow(2, power, mod)); + } + return ans; + } +}; diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.go b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.go new file mode 100644 index 0000000000000..28d4c1c4304b6 --- /dev/null +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.go @@ -0,0 +1,75 @@ +const m = 50 + +var cnt [m + 1]int64 +var s [m + 1]int64 +var p int64 = 1 + +func init() { + cnt[0] = 0 + s[0] = 0 + for i := 1; i <= m; i++ { + cnt[i] = cnt[i-1]*2 + p + s[i] = s[i-1]*2 + p*(int64(i)-1) + p *= 2 + } +} + +func numIdxAndSum(x int64) (int64, int64) { + var idx, totalSum int64 + for x > 0 { + i := 63 - bits.LeadingZeros64(uint64(x)) + idx += cnt[i] + totalSum += s[i] + x -= 1 << i + totalSum += (x + 1) * int64(i) + idx += x + 1 + } + return idx, totalSum +} + +func f(i int64) int64 { + l, r := int64(0), int64(1)<> 1 + idx, _ := numIdxAndSum(mid) + if idx < i { + l = mid + } else { + r = mid - 1 + } + } + + _, totalSum := numIdxAndSum(l) + idx, _ := numIdxAndSum(l) + i -= idx + x := l + 1 + for j := int64(0); j < i; j++ { + y := x & -x + totalSum += int64(bits.TrailingZeros64(uint64(y))) + x -= y + } + return totalSum +} + +func qpow(a, n, mod int64) int64 { + ans := int64(1) % mod + a = a % mod + for n > 0 { + if n&1 == 1 { + ans = (ans * a) % mod + } + a = (a * a) % mod + n >>= 1 + } + return ans +} + +func findProductsOfElements(queries [][]int64) []int { + ans := make([]int, len(queries)) + for i, q := range queries { + left, right, mod := q[0], q[1], q[2] + power := f(right+1) - f(left) + ans[i] = int(qpow(2, power, mod)) + } + return ans +} diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.java b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.java new file mode 100644 index 0000000000000..a59c420b7f6ce --- /dev/null +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.java @@ -0,0 +1,79 @@ +class Solution { + private static final int M = 50; + private static final long[] cnt = new long[M + 1]; + private static final long[] s = new long[M + 1]; + + static { + long p = 1; + for (int i = 1; i <= M; i++) { + cnt[i] = cnt[i - 1] * 2 + p; + s[i] = s[i - 1] * 2 + p * (i - 1); + p *= 2; + } + } + + private static long[] numIdxAndSum(long x) { + long idx = 0; + long totalSum = 0; + while (x > 0) { + int i = Long.SIZE - Long.numberOfLeadingZeros(x) - 1; + idx += cnt[i]; + totalSum += s[i]; + x -= 1L << i; + totalSum += (x + 1) * i; + idx += x + 1; + } + return new long[] {idx, totalSum}; + } + + private static long f(long i) { + long l = 0; + long r = 1L << M; + while (l < r) { + long mid = (l + r + 1) >> 1; + long[] idxAndSum = numIdxAndSum(mid); + long idx = idxAndSum[0]; + if (idx < i) { + l = mid; + } else { + r = mid - 1; + } + } + + long[] idxAndSum = numIdxAndSum(l); + long totalSum = idxAndSum[1]; + long idx = idxAndSum[0]; + i -= idx; + long x = l + 1; + for (int j = 0; j < i; j++) { + long y = x & -x; + totalSum += Long.numberOfTrailingZeros(y); + x -= y; + } + return totalSum; + } + + public int[] findProductsOfElements(long[][] queries) { + int n = queries.length; + int[] ans = new int[n]; + for (int i = 0; i < n; i++) { + long left = queries[i][0]; + long right = queries[i][1]; + long mod = queries[i][2]; + long power = f(right + 1) - f(left); + ans[i] = qpow(2, power, mod); + } + return ans; + } + + private int qpow(long a, long n, long mod) { + long ans = 1 % mod; + for (; n > 0; n >>= 1) { + if ((n & 1) == 1) { + ans = ans * a % mod; + } + a = a * a % mod; + } + return (int) ans; + } +} diff --git a/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.py b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.py new file mode 100644 index 0000000000000..fdb9da3d8f2f9 --- /dev/null +++ b/solution/3100-3199/3145.Find Products of Elements of Big Array/Solution.py @@ -0,0 +1,47 @@ +m = 50 +cnt = [0] * (m + 1) +s = [0] * (m + 1) +p = 1 +for i in range(1, m + 1): + cnt[i] = cnt[i - 1] * 2 + p + s[i] = s[i - 1] * 2 + p * (i - 1) + p *= 2 + + +def num_idx_and_sum(x: int) -> tuple: + idx = 0 + total_sum = 0 + while x: + i = x.bit_length() - 1 + idx += cnt[i] + total_sum += s[i] + x -= 1 << i + total_sum += (x + 1) * i + idx += x + 1 + return (idx, total_sum) + + +def f(i: int) -> int: + l, r = 0, 1 << m + while l < r: + mid = (l + r + 1) >> 1 + idx, _ = num_idx_and_sum(mid) + if idx < i: + l = mid + else: + r = mid - 1 + + total_sum = 0 + idx, total_sum = num_idx_and_sum(l) + i -= idx + x = l + 1 + for _ in range(i): + y = x & -x + total_sum += y.bit_length() - 1 + x -= y + return total_sum + + +class Solution: + def findProductsOfElements(self, queries: List[List[int]]) -> List[int]: + return [pow(2, f(right + 1) - f(left), mod) for left, right, mod in queries]