LeetCode in Kotlin

3444. Minimum Increments for Target Multiples in an Array

Hard

You are given two arrays, nums and target.

In a single operation, you may increment any element of nums by 1.

Return the minimum number of operations required so that each element in target has at least one multiple in nums.

Example 1:

Input: nums = [1,2,3], target = [4]

Output: 1

Explanation:

The minimum number of operations required to satisfy the condition is 1.

Example 2:

Input: nums = [8,4], target = [10,5]

Output: 2

Explanation:

The minimum number of operations required to satisfy the condition is 2.

Example 3:

Input: nums = [7,9,10], target = [7]

Output: 0

Explanation:

Target 7 already has a multiple in nums, so no additional operations are needed.

Constraints:

Solution

import kotlin.math.min

class Solution {
    fun minimumIncrements(nums: IntArray, target: IntArray): Int {
        val m = target.size
        val fullMask = (1 shl m) - 1
        val lcmArr = LongArray(1 shl m)
        for (mask in 1..<(1 shl m)) {
            var l: Long = 1
            for (j in 0..<m) {
                if ((mask and (1 shl j)) != 0) {
                    l = lcm(l, target[j].toLong())
                }
            }
            lcmArr[mask] = l
        }
        val inf = Long.Companion.MAX_VALUE / 2
        var dp = LongArray(1 shl m)
        for (i in 0..<(1 shl m)) {
            dp[i] = inf
        }
        dp[0] = 0
        for (x in nums) {
            val newdp = dp.clone()
            for (mask in 1..<(1 shl m)) {
                val l = lcmArr[mask]
                val r = x % l
                val cost = (if (r == 0L) 0 else l - r)
                for (old in 0..<(1 shl m)) {
                    val newMask = old or mask
                    newdp[newMask] = min(newdp[newMask], (dp[old] + cost))
                }
            }
            dp = newdp
        }
        return dp[fullMask].toInt()
    }

    private fun gcd(a: Long, b: Long): Long {
        return if (b == 0L) a else gcd(b, a % b)
    }

    private fun lcm(a: Long, b: Long): Long {
        return a / gcd(a, b) * b
    }
}