PROBLEM LINKS
DIFFICULTY
HARD
PREREQUISITES
Generating Functions, Partial Function Decomposition, Complex Numbers
PROBLEM
In a currency there are N denominations of coins, given as an array D. All elements in D are pairwise distinct and pairwise relatively prime.
Can you use this property of the coinage to design a fast algorithm to answer queries of the type
- How many ways exist of making change for target S? Of course, the answer should be found modulo MOD.
EXPLANATION
There is a popular technique for creating a generating function for this the number of ways of making change. Let us quickly look at the appropriate generating function that gives us the answer.
G(x) = PROD ( SUMMA ( xu * d, 0 ≤ u < ∞ ), d ∈ D )
The coefficient of xS in G(x) (modulo MOD), will be the answer.
We can multiply and divide each term inside the product in G(x) with (1-xd). This gives us the following simplified expression for G(x)
1 PROD ( ------ , d ∈ D ) ... (i) 1 - xd
We can re-write (i) as
1 1 -------- * PROD ( -------------------- , d ∈ D ) ... (ii) (1 - x)n 1 + x + x2 + ... xd-1
For some polynomial,
f(x) = 1 + x + x2 + ... xn-1
And an complex nth root of unity wn,
wn = eι 2π/n
We can easily prove that
f(wni) = 0, 1 ≤ i < n
Thus, we can factorize f(x) as
(x - wn) (x - wn2) ... (x - wnn-1)
Now, we can transform (ii) into
1 1 -------- * PROD ( PROD ( ------- , 1 ≤ i < d ) , d ∈ D ) ... (iii) (1 - x)n x - wdi
From the problem description, we are assured that all d are pairwise prime. This is a very important because this means that all wdi are also pairwise distinct! This means that each wdi is a simple root of the denominator. Hence, the Partial Fraction Expansion of
1 PROD ( PROD ( ------- , 1 ≤ i < d ) , d ∈ D ) ... (iv) x - wdi
Can eventually be written as
P(wdi) SUM ( SUM ( ------- , 1 ≤ i < d ) , d ∈ D ) ... (v) x - wdi
Let us find P(x). Note that P(x) will depend on d. Hence all the calculations below should be assumed to already be within the closure with i and d available from (v).
We know that
1
1
PROD ( 1 + x + x2 + … xd’-1 , d’ ∈ D )
P(w<sub>d'</sub><sup>j</sup>)
= SUM ( SUM ( -------- , 1 ≤ j < d ) , d' ∈ D ) ... (vi)
x - w<sub>d'</sub><sup>j</sup>
Let us multiply the LHS and RHS with (x - wdi).
x - wdi
x - wdi
PROD ( 1 + x + x2 + … xd’-1 , d’ ∈ D )
P(w<sub>d'</sub><sup>j</sup>)
= (x - w<sub>d</sub><sup>i</sup>) * SUM ( SUM ( -------- , 1 ≤ j < d' ) , d' ∈ D ) ... (vii)
x - w<sub>d</sub><sup>i</sup>
Now, let us keep x = wdi in (vii).
- The RHS reduces to P(wdi), since all other terms become 0.
- The LHS becomes of the form 0 / 0
- But we know that this function is well defined for all real x
Thus, we use the L’Hopital’s rule for the LHS and take the derivatives of the numerator and the denominator. Out of the N terms in the first derivative of the denominator of the LHS we note that only one of them is non zero. Hence, we get
1 P(wdi) = ------------------------------------------- (1 + 2wdi + 3wd2i + ... (d-1)wd(d-2)i) * PROD ( 1 + wdi + wd2i + ... wd(d'-1)i , d' ∈ D AND d' ≠ d )
Now let us simplify the above a bit. We use the Sum of AGP to simplify the first term. We also use
- wdd = 1
-
SUM ( wdi , 0 ≤ i < d ) = 0
- we used this above already when we said that all except one term in the first derivative of the denominator of the LHS will be 0
to further simplify things above.
For simplicity, let us define P(d,y). y will always be a complex dth root of unity.
y * (y - 1) P(d,y) = ------------------------------------------------------ d * PROD ( SUM ( yi, 0 ≤ i ≤ (d' modulo d) ), d' ∈ D )
Now, expression for G(x) looks like
1 P(wdi) -------- * SUM ( SUM ( ------- , 1 ≤ i < d ) , d ∈ D ) ... (viii) (1 - x)n x - wdi
We use the following Partial Fraction Decomposition to furthur break down the above
1 1 -------- * ------- (1 - x)n (x - y) 1 1 = ------------------ + SUM ( ---------------------- , 1 ≤ i ≤ N) (1 - y)N * (x - y) (1 - y)N-i+1 * (x - 1)i
(This too can be proven easily by repeatedly using the L’Hopital’s Rule!)
Now, we have G(x) broken into non reducible fractions.
P(d,wdi) P(d,wdi) G(x) = SD( Si ( ---------------------- + Sj ( ----------------------- ) ) ) (1 - wdi)N * (x - wdi) (1 - wdi)N-j * (x - 1)j Where, 0 ≤ j < N 1 ≤ i < d d ∈ D
Now, we can use the Generalized Binomial Theorem to find the coefficient of xS in G(x). The expression for the coefficient will look like
Ud(wdi) SUM ( SUM ( ------- , 1 ≤ i < d ) , d ∈ D ) Vd(wdi)
Let, Qd(x) = 1 + x + x2 + … xd-1
As we can see above, we want to calculate
- Ud(y) / Vd(y) for some y, such that Qd(y) = 0
Let Zd(y) be a polynomial of degree strictly less than d-1 such that
- Vd(y) * Zd(y) = 1 modulo Qd(y) = 0
This means that
- Vd(y) * Zd(y) = 1 + Rd(y) * Qd(y)
Now,
-
1 / Vd(y) = Zd(y) / (Vd(y) * Zd(y))
- = Zd(y) / (1 + Rd(y) * Qd(y))
But, Qd(y) = 0 for all y that we want to evaluate Vd(y) for.
Thus, we can run the Extended Euclid’s Algorithm for univariate polynomials with coefficients in a field to find the inverse of Vd(y) modulo Qd(y).
This gives us a polynomial Td(y) to play with!
The answer will be
SUM ( SUM ( Td(wdi) , 1 ≤ i < d ) , d ∈ D )
But, calculating Td(y) requires a lot of calculations in complex numbers whose coefficients are irrational. We cannot find the result modulo MOD just with this knowledge yet.
Now comes another proof that simply eliminates all the complex numbers from all the calculations!
Let
Td(y) = t0 + t1y + t2y2 + ... td-1yd-1
We can infer from all the above discussions that
- Ud(y) has degree 1
- Zd(y) has degree d-2
- Thus, Td(y) has degree d-1
SUM ( Td(wdi) , 1 ≤ i < d ) = SUM ( tp * SUM ( wdi * p , 1 ≤ i < d ) , 0 ≤ p < d ) = SUM ( tp * SUM ( wdi * p , 1 ≤ i < d ) , 1 ≤ p < d ) + t0 * (d - 1) We know that Qd(wdp) = 0 for any non-zero t. Thus, SUM ( wdi * p , 1 ≤ i < d ) = -1 We can simplify the above as = SUM ( -tp, 1 ≤ p < d ) + t0 * (d - 1) = d * t0 - SUM ( tp , 0 ≤ p < d ) = d * Td(0) - Td(1)
This allows us to use the polynomial Zd(y) that we generated for evaluation only for 0 and 1.
It is worth noting that the large S is not a problem at all while solving the problem. It appears only in the exponent of wd. This lets us consider S modulo d conveniently.
Doing this for each d, solves the problem.
There lie several simplifications to the polynomials along the way that can be exploited to make the code neater.
SETTER’S SOLUTION
Can be found here.
TESTER’S SOLUTION
Can be found here.