LeetCode in Kotlin

3653. XOR After Range Multiplication Queries I

Medium

You are given an integer array nums of length n and a 2D integer array queries of size q, where queries[i] = [li, ri, ki, vi].

For each query, you must apply the following operations in order:

Return the bitwise XOR of all elements in nums after processing all queries.

Example 1:

Input: nums = [1,1,1], queries = [[0,2,1,4]]

Output: 4

Explanation:

Example 2:

Input: nums = [2,3,1,5,4], queries = [[1,4,2,3],[0,2,1,2]]

Output: 31

Explanation:

Constraints:

Solution

class Solution {
    private fun modPow(a0: Long, e0: Long): Long {
        var a = a0 % MOD
        var e = e0
        var res = 1L
        while (e > 0) {
            if ((e and 1L) == 1L) {
                res = (res * a) % MOD
            }
            a = (a * a) % MOD
            e = e shr 1
        }
        return res
    }

    private fun modInv(a: Long): Long {
        return modPow(a, MOD - 2L)
    }

    fun xorAfterQueries(nums: IntArray, queries: Array<IntArray>): Int {
        val n = nums.size
        val b = kotlin.math.sqrt(n.toDouble()).toInt()
        val small = HashMap<Int, Array<LongArray?>>()

        for (query in queries) {
            val l = query[0]
            val r = query[1]
            val k = query[2]
            val v = query[3]
            if (k > b) {
                var i = l
                while (i <= r) {
                    nums[i] = ((nums[i].toLong() * v.toLong()) % MOD).toInt()
                    i += k
                }
            } else {
                val byResidue = small.getOrPut(k) { arrayOfNulls<LongArray>(k) }
                val res = l % k
                if (byResidue[res] == null) {
                    val len = (n - res + k - 1) / k
                    byResidue[res] = LongArray(len + 1) { 1L }
                }
                val diff = byResidue[res]!!
                val jStart = (l - res) / k
                val jEnd = (r - res) / k
                diff[jStart] = (diff[jStart] * v.toLong()) % MOD
                if (jEnd + 1 < diff.size) {
                    diff[jEnd + 1] = (diff[jEnd + 1] * modInv(v.toLong())) % MOD
                }
            }
        }
        for ((k, byResidue) in small) {
            for (res in 0 until k) {
                val diff = byResidue[res] ?: continue
                var mul = 1L
                for (j in 0 until diff.size - 1) {
                    mul = (mul * diff[j]) % MOD
                    val idx = res + j * k
                    if (idx < n) {
                        nums[idx] = ((nums[idx].toLong() * mul) % MOD).toInt()
                    }
                }
            }
        }
        var ans = 0
        for (x in nums) {
            ans = ans xor x
        }
        return ans
    }

    companion object {
        private const val MOD = 1000000007L
    }
}