|
| 1 | +class Solution { |
| 2 | + public int magicalSum(int m, int k, int[] nums) { |
| 3 | + int[][] comb = getComb(m, m); |
| 4 | + Integer[][][][] mem = new Integer[m + 1][k + 1][nums.length + 1][m + 1]; |
| 5 | + return dp(m, k, 0, 0, nums, mem, comb); |
| 6 | + } |
| 7 | + |
| 8 | + private static final int MOD = 1_000_000_007; |
| 9 | + |
| 10 | + private int dp(int m, int k, int i, int carry, int[] nums, Integer[][][][] mem, int[][] comb) { |
| 11 | + if (m < 0 || k < 0 || (m + Integer.bitCount(carry) < k)) |
| 12 | + return 0; |
| 13 | + if (m == 0) |
| 14 | + return k == Integer.bitCount(carry) ? 1 : 0; |
| 15 | + if (i == nums.length) |
| 16 | + return 0; |
| 17 | + if (mem[m][k][i][carry] != null) |
| 18 | + return mem[m][k][i][carry]; |
| 19 | + int res = 0; |
| 20 | + for (int count = 0; count <= m; count++) { |
| 21 | + final long contribution = comb[m][count] * modPow(nums[i], count) % MOD; |
| 22 | + final int newCarry = carry + count; |
| 23 | + res = (int) ((res + |
| 24 | + (long) dp(m - count, k - (newCarry % 2), i + 1, newCarry / 2, nums, mem, comb) * |
| 25 | + contribution) % |
| 26 | + MOD); |
| 27 | + } |
| 28 | + return mem[m][k][i][carry] = res; |
| 29 | + } |
| 30 | + |
| 31 | + // C(n, k) = C(n - 1, k) + C(n - 1, k - 1) |
| 32 | + private int[][] getComb(int n, int k) { |
| 33 | + int[][] comb = new int[n + 1][k + 1]; |
| 34 | + for (int i = 0; i <= n; i++) |
| 35 | + comb[i][0] = 1; |
| 36 | + for (int i = 1; i <= n; i++) |
| 37 | + for (int j = 1; j <= k; j++) |
| 38 | + comb[i][j] = (comb[i - 1][j] + comb[i - 1][j - 1]) % MOD; |
| 39 | + return comb; |
| 40 | + } |
| 41 | + |
| 42 | + private long modPow(long x, long n) { |
| 43 | + if (n == 0) |
| 44 | + return 1; |
| 45 | + if (n % 2 == 1) |
| 46 | + return x * modPow(x % MOD, n - 1) % MOD; |
| 47 | + return modPow(x * x % MOD, n / 2) % MOD; |
| 48 | + } |
| 49 | +} |
0 commit comments