Timeline
Timeline
2025-10-12
init
A combinatorial counting problem that uses DP to simulate binary addition carry rules, advanced dynamic programming,__builtin_popcount
Problem:
Attempt exhaustive enumeration
At first I only thought of exhaustive enumeration, but I didn’t even enumerate completely, frustrating.
1 |
|
Dynamic programming
The solution to this problem still uses dynamic programming, but it is high-order dynamic programming.
Problem
Given two integersMandK, and an integer arraynums。
An integer sequenceseqif it satisfies the following conditions, is calledmagicSequence:
seqhas sequence length ofM。0 <= seq[i] < nums.length2^seq[0] + 2^seq[1] + ... + 2^seq[M - 1]ofbinary formhasKaset bits。
This sequence’sarray productis defined asprod(seq) = (nums[seq[0]] * nums[seq[1]] * ... * nums[seq[M - 1]])。
Return all validmagicsequence’sarray productofsum 。
Since the answer may be large, return the result modulo10^9 + 7modulo。
set bitrefers to a bit that is 1 in the binary representation of a number.
What we need to do is:
- Given an array
nums, lengthn - Take a sequence of length
Msequenceseq(elements from nums can be chosen repeatedly) - Condition:
2^seq[0] + ... + 2^seq[M-1]has in binaryKones - Array product:
prod(seq) = nums[seq[0]] * ... * nums[seq[M-1]] - Goal: sum of products of all magic sequence arrays (mod 1e9+7)
Number of sequence permutations
Suppose we start fromnumsindex0..n-1take numbers:
- Each number
itookr_ipieces - Total satisfies:
r_0 + r_1 + ... + r_{n-1} = M
Number of permutations of length M:
Formula for number of permutations of length M
Number of permutations without considering duplicate numbers
- Ifall numbers are distinct, then the number of sequence permutations of length M isM!
- Because M distinct elements can have M! permutations
Consider repeated digits
- If some digits appear repeatedly, for example:
- Swapping repeated digits does not produce a new sequence
- In combinatorics, we need todivide by the factorial of each repeated digit, to eliminate the effect of repeated permutations
- Suppose digit i appears
r_itimes, the total permutation formula is:This is the classicmultiset permutation formula: number of permutations of length M = factorial of total elements / factorial of each repeated element
Array product
Array product formula
The array product of a sequence is defined as:
- If the number i appears in the sequence
r_itimes, then the product can be written as:
- Combining the number of permutations, a certain sequence { r0, r_1, r_2, … ,r } the total contribution of the sequence is:
- Explanation:
- The array product corresponding to each sequence of length M is
∏ nums[i]^r_i- There are a total of
M! / ∏ r_i!permutations (because permutations of repeated numbers are not considered new sequences)- Somultiplying them gives the total contribution of that combination
Dynamic programming approach
Use DP to simulate the carry rule of binary addition
- Enumerate all possible
r_i(the number of occurrences of each number) is very complex - Dynamic programming approach:Consider each number in nums one by one
State definition
f[i][j][p][q]represents:- Already considered the first
inumbers (nums[0…i]) - Total taken
j - The sum of the lower i bits of the current mask (carry state) is
p - The number of set bits in the lower i bits is
q - Value = sum of all corresponding sequences
∏ r_t! * nums[t]^r_twhich is the sum of contributions of all these cases
- Already considered the first
Transition formula
When considering thei+1th number:
- Assume we choose
ranums[i+1] - New status:
p/2andp%2the role of:- Simulate the binary of mask from low to high bits
p % 2= number of low bits setp / 2= mask after shifting up one bit
Initialization
- For
i=0, that is the first number:
- Low 0 position bits = 0
Result
- Total set bits of mask = set bits of high mask + low q
1 | if (__builtin_popcount(p) + q == K) |
Code implementation
The code uses many techniques, here we first introduce the following
Fast exponentiation
Core idea
Using the exponent’sbinary representationandproperty of splitting powers:
That is:
- Take
yas binary; - Each time square the base, which is equivalent to doubling the exponent;
- If the current binary digit is 1, multiply this term into the result
Example
Suppose we want to calculate:
The binary of 13 is:1101₂ = 8 + 4 + 0 + 1
So:
We can obtain these powers by repeatedly squaring:
| Step | Power | Result |
|---|---|---|
| 3¹ | 3 | |
| 3² | 9 | |
| 3⁴ | 81 | |
| 3⁸ | 6561 |
Therefore:
Corresponding algorithm logic
1 | long long quickPow(long long x, long long y) { |
Fermat’s Little Theorem
According toFermat’s Little Theorem (Fermat’s Little Theorem):
Therefore:
Fermat’s Little Theorem requires that p must be a prime number
That is to say:
The modular inverse of a number = this number raised to the power (mod - 2) modulo mod.
Final code implementation
1 |
|
