Let's say we have a logical function FirstPlayerWin (FPW) that takes two arguments: the number of candies on the left (c) and the last move (l), that is, the number of candies accepted in the previous round, which is 0 on the first move. The subroutine returns true if and only if the first player playing in this situation is guaranteed victory.
The main case is that FPW (0, l) = false for any l! = 1
Otherwise, to calculate FPW (c, l), FPW (c, l) is true if, for any x <= M, x <= c, x! = L, FPW (c - x, x) is false. Otherwise, this is not true. This is where dynamic programming takes place, because now FPW calculation is reduced to FPW calculation for lower values ββof c.
However, for storing records for this wording, records in table N * M will be required, where, since the solution you specified uses only records in table 2N.
The reason for this is that if FPW (c, 0) is true (the first player wins if any move is available in chocolate c), but FPW (c, x) is incorrect for x> 0, FPW (c, y) for and y ! = x must be true. This is because if negating the movement of x makes the player lose, that is, the player will only win by playing x, then moving x is available when y is instead prohibited. Therefore, it is enough to store for any account βcβ no more than one forbidden move, which forces the player to lose there. Thus, you can reorganize the dynamic programming problem so that instead of storing the full two-dimensional array FPW (c, x) you have two arrays, one stores the values ββFPW (c, 0), and the other stores single forbidden movements that cause the first the player will lose, not win, if any.
How you get to the exact text of the quoted C program remains as an exercise for the reader.