R= A ⊗ B is // R initially all zeros 1: if |A| < |B| ⇒ A ⟷ B 2: if |B|=1 ⇒ R= A × B .done. 3: M= ⌊|A|/2⌋ 4: a1:a0 = A s.t. |a1|= |A|-M, |a0|= M 5: if M ≥ |B| 6: R = a0 ⊗ B 7: T((|a1|+|B|)) = a1 ⊗ B 8: R{M} += T 9: .done. 10: b1:b0 = B s.t. |b1|= |B|-M, |b0|= M 11: R= a0 ⊗ b0 12: R{2M}= a1 ⊗ b1 13: Sa,Ta = a0 ⊖ a1 14: Sb,Tb = b1 ⊖ b0 15: P((|Ta|+|Tb|))= Ta ⊗ Tb 16: mixed_sum(R, M) 17: R{M} ⊕= Sa XOR Sb : PWe are now left with the following variables allocated at shown lines:
There is no way to eliminate P, so we have to allocate some memory that. For Ta and Tb, we might get away with using the memory of a1 and b0, if we're allowed to modify our input. However, this isn't really an option because the recursive calls at (11) and (12) would mess up a0/1 and b0/1. Therefore, we're stuck with allocating memory for all variables listed above. Now let's look at how much memory we need for each variable.
For P, the answer is obvious from the code. It's |Ta|+|Tb|.
Ta is a difference of a0 and a1. Therefore, its length is the maximum of |a0| and |a1|.
|Ta| = max(|a0|,|a1|) |a1|= |a0|= M , if |A| is even |a1|= |a0|+1= M+1, if |A| is odd so, |Ta|= |a1|= ceil(|A|/2)Since |Tb|≤|Ta| (because |B|≤|A|), allocating the same space for it will also suffice.
So, the total requirement |P|+|Ta|+|Tb| is:
|P|= |Ta| + |Tb| Q= |P|+|Ta|+|Tb| = 2*(|Ta|+|Tb|) |Tb|≤|Ta| Q ≤ 4*|Ta|If we allocate the maximum amount,
Q= 4*ceil(|A|/2) = 2*|A| if |A| is even, = 2*(|A|+1) if |A| is oddNow, notice that Q depends only on |A| since we made sure that B is shorter than A at the beginning. However, this won't be true all the time as we descend down the recursive call tree. At some point, |A| will get smaller than |B| and the value of |A| will increase. I will deal with this now. Let's call a and b the lengths of |A| and |B| in a particular call to our function. Then we have:
Q(a,b)= 4*ceil( max(a,b) / 2 )Note that this memory is needed to execute the current call of the function and it doesn't include memory needed for the recursive calls.
Writing down the recursive formula is easy enough, but solving it isn't. So, I'm going to simply write some function that emulates ⊗ but only computes the necessary space instead of doing the actual computation. Maybe I can fit some polynomial to that.
Here is the code that does that:
100: int kspace(int a, int b) 101: { 102: int M,a0,b0,a1,b1,Ta,Tb, R; 103: if (a<b) { int t; t=a; a=b; b=t; } 104: if (b==1) return 0; 105: M= a/2; // = floor(a/2) 106: a0= M; a1= a-M; 107: if (b<=M) return a1+b + max2(kspace(a0,b), kspace(a1,b)); 108: b0= M; b1= b-M; 109: Ta= max2(a1,a0); 110: Tb= max2(b1,b0); 111: R= max3(kspace(a0,b0), kspace(a1,b1), kspace(Ta,Tb)); 112: return R+ 2*(Ta+Tb); 113: }This results in a value somewhere around 4*max(A,B), but the latter underestimates kspace(A,B). I wonder if I can simplify kspace and get some sort of a closed form. We know that
a1= ceil(a/2) a0= floor(a/2)So, their maximum is a1. This can be replaced in (109).
109: Ta= max2(a1,a0); 109: Ta= a1;This makes Ta and its computation redundant. We also know that a0=b0=M due to (106) and (108). Let's replace all that:
100: int kspace(int a, int b) 101: { 102: int M,a1,b1,Tb, R; 103: if (a<b) { int t; t=a; a=b; b=t; } 104: if (b==1) return 0; 105: M= a/2; 106: a1= a-M; 107: if (b<=M) return a1+b + max2(kspace(M,b), kspace(a1,b)); 108: b1= b-M; 109: Tb= max2(b1,M); 110: R= max3(kspace(M,M), kspace(a1,b1), kspace(a1,Tb)); 111: return R+ 2*(a1+Tb); 112: }
G(x)= kspace(x,x) : replace a and b by x. 202: int M,x1,x1,Tx, R; 203: if (x<x) { int t; t=a; a=b; b=t; } 204: if (x==1) return 0; 205: M= x/2; 206: x1= x-M; 207: if (x<=M) return a1+b+max2(kspace(M,b), kspace(a1,b)); 208: x1= x-M; 209: Tx= max2(x1,M); 210: R= max3(kspace(M,M), kspace(x1,x1), kspace(x1,Tx)); 211: return R+ 2*(a1+Tx);We can see that the branches in (203) and (207) are never taken. (208) repeats the computation at (206). Computation of Tx is the same as the computation of Ta from before, so we have Tx=x1 again. Making these changes:
200: int G(int x) 201: { 202: int M,x1,R; 203: if (x==1) return 0; 204: M= x/2; 205: x1= x-M; 206: R= max3(kspace(M,M), kspace(x1,x1), kspace(x1,x1)); 207: return R+ 2*(x1+x1); 208: }Since all calls to kspace have symmetrical arguments, these can be replaced by G. Further simplifying (206) and (207),
200: int G(int x) 201: { 202: int M,x1,R; 203: if (x==1) return 0; 204: M= x/2; 205: x1= x-M; 206: R= max2( G(M), G(x1) ); 207: return R+ 4*x1; 208: }This becomes even easier if we split G into two parts, with even and odd x.
200: int G(int x) { if (x%2) return G_odd(x); 201: else return G_even(x); } 202: int G_even(x) 203: { 204: int M,x1,R; 205: if (x==1) return 0; // impossible x is even 206: M= x/2; 207: x1= x-M; 208: R= max2(G(M), G(x1)); 209: return R+4*x1; 210: } 211: 212: int G_odd(x) 213: { 214: int M,x1,R; 215: if (x==1) return 0; 216: M= x/2; 217: x1= x-M; 218: R= max2(G(M), G(x1)); 219: return R+4*x1; 220: }For the even case, we can eliminate (205). Furthermore, we know that x1=M. Therefore, the max2 call at (208) also becomes useless. So, G_even becomes:
202: int G_even(x) 203: { 204: int M; 206: M= x/2; 209: return G(M)+4*M; 210: }For the odd case, x1=M+1. Replacing this value into the function:
212: int G_odd(x) 213: { 214: int M,R; 215: if (x==1) return 0; 216: M= x/2; 218: R= max2(G(M), G(M+1)); 219: return R+4*(M+1); 220: }So, we have the following series:
G(1)= 0 G(2M)= G(M) + 4*M [1] G(2M+1)= max(G(M), G(M+1)) + 4*M+4 [2]If we calculate the difference [2]-[1], then we see that it's always positive.
G(2M+1)-G(2M)= max(G(M),G(M+1))+4M+4-G(M)-4M = max(G(M),G(M+1))-G(M)+4 since max(G(M),X) ≥ G(M), G(2M+1)-G(2M)> 0 [A]We can do a similar calculation for G(2M+2).
G(2M+2)= G(M+1) + 4 (M+1)= G(M+1)+4M+4 [3] subtracting [2] from [3], Δ(M)= G(2M+2)-G(2M+1) = G(M+1)+4M+4-max(G(M),G(M+1)-4M-4 = G(M+1)-max(G(M),G(M+1)) = G(M+1) + min(-G(M), -G(M+1)) = min(G(M+1)-G(M), G(M+1)-G(M+1)) = min(G(M+1)-G(M), 0)Here, we have two cases, M can be odd or even. Let M=2k first,
Δ(M)=Δ(2k)= min( G(2k+1)-G(2k), 0) due to [A], G(2k+1) - G(2k) > 0 = 0Now let's set M=2k+1.
Δ(M)=Δ(2k+1)= min(G(2k+1+1)-G(2k+1), 0) = min(G(2k+2)-G(2k+1), 0) = min(Δ(k), 0) (from definition of Δ(M))Now we have the following:
Δ(M)= 0 , even M Δ(M)= min(Δ((M-1)/2)),0), odd MIf we set m0=M, we can define the function as:
Δ(mi)= 0, even mi Δ(mi)= min(Δ(mi+1),0), odd mi mi+1= (mi-1)/2When we iterate this, eventually mi will become either 0 or an even number. This will result in an expression with a bunch of min() functions as zeros for arguments. The value of that expression will of course be 0. So we have shown that, for both odd and even M, Δ(M) is 0. Therefore,
G(2M+1) > G(2M) G(2M+2) = G(2M+1)Which indicates a non-decreasing G. We can then remove the max operator from [2]:
G(2M+1)= max(G(M), G(M+1)) + 4*M+4 [2] G(2M+1)= G(M+1) + 4*M+4 [2]Replacing this in our original triple equations:
G(1)= 0 G(2M)= G(M) + 4*M [1] G(2M+1)= G(M+1) + 4*M+4 [2]This can be rewritten with the ceiling function.
ceil((2M+1)/2)= M+1 ceil((2M)/2)= M G(1)= 0 G(M)= G(ceil(M/2))+4*ceil(M/2)This isn't a closed form, but log-time with regards to magnitude of M, which is pretty good. Let's try this:
int G(int x) { if (x==1) return 0; return G(CEIL(x,2)) + 4*CEIL(x,2); }It does work pretty well. When I plot it against 4*x, there is very little difference. 4*x+60 exceeds G(x) up until 64K digits, so that's what I'm going to use. Here is the plot of G(x)-4x:
f(x)=0, x≤1 f(x)=f(x/2)+2x+4, x>1overestimates G(x). Therefore, 4(x+ln(x)/ln(2)) is a good upper bound. If kspace(a,b) is increasing with regards to b, then G(a) is an upper bound on kspace(a,b) where b≤a. That's the only thing I need to prove from now on.
200: P(X)= kspace(X+1,X) // let a= X+1, b= X 201: { 202: int M,a1,b1,Tb, R; 203: if (a<b) { int t; t=a; a=b; b=t; } 204: if (b==1) return 0; 205: M= a/2; 206: a1= a-M; 207: if (b<=M) return a1+b + max2(kspace(M,b), kspace(a1,b)); 208: b1= b-M; 209: Tb= max2(b1,M); 210: R= max3(kspace(M,M), kspace(a1,b1), kspace(a1,Tb)); 211: return R+ 2*(a1+Tb); 212: }We can immediately deduce that branches at (203) and (207) are never taken. Let's compute the rest of the numbers:
200: P(x)= kspace(x+1,x) // let a= x+1, b= x 201: { 202: int M,a1,b1,Tb, R; 204: if (b==1) return 0; ⇒ if (x==1) return 0; 205: M= a/2; ⇒ M=int((x+1)/2)=⌈x/2⌉ 206: a1= a-M; ⇒ a1=x+1-⌈x/2⌉=1+⌊x/2⌋ 208: b1= b-M; ⇒ b1=x-⌈x/2⌉=⌊x/2⌋ 209: Tb= max2(b1,M); ⇒ Tb=max2(⌈x/2⌉,⌊x/2⌋)=⌈x/2⌉ 210: R= max3(kspace(M,M), kspace(a1,b1), kspace(a1,Tb)); 211: return R+ 2*(a1+Tb); 212: }Now we can get rid of all the variables and write this properly.
P(1)= 0, P(x≠1)= max(kspace(⌈x/2⌉,⌈x/2⌉), kspace(1+⌊x/2⌋,⌊x/2⌋), kspace(1+⌊x/2⌋,⌈x/2⌉))+ 2*(1+⌊x/2⌋+⌈x/2⌉)The first call to kspace is in fact G(). The second one is a call to P(). I will let the third one stay as is for now. The final expression is just 2(1+x).
P(1)= 0, P(x≠1)= max(G(⌈x/2⌉), P(⌊x/2⌋), kspace(1+⌊x/2⌋,⌈x/2⌉))+ 2x+2The third term in the max function is actually redundant.
for even x, ⌈x/2⌉=⌊x/2⌋ kspace(1+⌊x/2⌋,⌈x/2⌉)= kspace(1+⌊x/2⌋,⌊x/2⌋)= P(⌊x/2⌋) for odd x, ⌈x/2⌉=⌊x/2⌋+1 kspace(1+⌊x/2⌋,⌈x/2⌉)= kspace(⌈x/2⌉,⌊x/2⌋)= G(⌈x/2⌉)Both of these terms are already part of the max() expression. They can be removed safely.
P(1)= 0, P(x≠1)= max(G(⌈x/2⌉), P(⌊x/2⌋))+ 2x+2Let's compare this to G(x≠1).
G(1)= 0 G(x)= G(⌈x/2⌉)+4⌈x/2⌉ P(x)-G(x)= max(G(⌈x/2⌉), P(⌊x/2⌋))+ 2x+2 - G(⌈x/2⌉)-4⌈x/2⌉ = max(G(⌈x/2⌉), P(⌊x/2⌋))-G(⌈x/2⌉)+2x+2-4⌈x/2⌉ since max(U,v) ≥ U, ⇒ max(U,v)-U≥0 P(x)-G(x) ≥ 0 + 2x+2-4⌈x/2⌉ for x=2k, P(x)-G(x) ≥ 2(2k)+2-4⌈2k/2⌉= 4k+2-4k= 2 for x=2k+1, P(x)-G(x) ≥ 2(2k+1)+2-4⌈(2k+1)/2⌉ P(x)-G(x) ≥ 4k+2+2-4(k+1)= 4k+4-4k-4=0We can conclude two things from here:
λ(x)=G(x+1)-P(x)= K(x+1,x+1)-K(x+1,x)This can be computed easily if we write down the formulas for P and G separately for odd and even cases.
P(1)= 0, P(x≠1)= max(G(⌈x/2⌉), P(⌊x/2⌋))+ 2x+2 P(a=2k)= max(G(k),P(k))+2(2k)+2 P(a=2k)= P(k)+4k+2 // since P(x)≥G(x) P(a=2k+1)= max(G(k+1),P(k))+ 2(2k+1)+2 P(a=2k+1)= max(G(k+1),P(k))+ 4k+4 G(1)= 0 G(a=2k)= G(k)+4k G(a=2k+1)= G(k+1)+4k+4We see that λ is defined recursively.
λ(1)=G(2)-P(1)= 4-0= 4 λ(a=2k)= G(2k+1)-P(2k)= G(k+1)+4k+4-[P(k)+4k+2] λ(a=2k)= 2+G(k+1)-P(k)= 2+λ(k) λ(a=2k+1)= G(2k+2)-P(2k+1) λ(a=2k+1)= G(k+1)+4(k+1)-[max(G(k+1),P(k))+4k+4] λ(a=2k+1)= G(k+1)+4k+4-max(G(k+1),P(k))-4k-4 λ(a=2k+1)= G(k+1)-max(G(k+1),P(k)) λ(a=2k+1)= G(k+1)+min(-G(k+1),-P(k)) λ(a=2k+1)= min(G(k+1)-G(k+1),G(k+1)-P(k)) λ(a=2k+1)= min(0, λ(k))It's easy to see that λ≥0. In fact, λ(x) is 0 for odd numbers (except for 1) and it counts the number of trailing zeros in binary for even numbers.
λ(1)= 4 λ(2k+1)= 0 λ(2N)= 2N+4 λ(2N(2m+1))= 2NExcept for a few numbers, this is going to be much smaller than N, since it grows logarithmically.
λ(1)= 4 λ(2)= 2.1+4= 6 λ(4)= 2.2+4= 8 λ(6)= 2.1= 2 λ(8)= 2.3+4= 10 λ(10)= 2.1= 2 λ(12)= 2.2= 4 λ(14)= 2.1= 2 λ(16)= 2.4+4= 12After this point, λ(x)<x. Since λ≥0, the definition of P can be simplified a little bit:
P(1)= 0 P(2k)= P(k)+4k+2 P(2k+1)= max(G(k+1),P(k))+4k+4 P(2k+1)= G(k+1)+4k+4= G(2k+1)Let's look at yet another difference now:
Φ(x)= G(x+1)-G(x)I have strong hunch that this is also always non-negative. Remember G:
G(1)= 0 G(2k)= G(k)+4k G(2k+1)= G(k+1)+4k+4Get on with it!
Φ(1)= G(2)-G(1)= 4-0= 4 Φ(2k)= G(2k+1)-G(2k) Φ(2k)= G(k+1)+4k+4-[G(k)+4k] Φ(2k)= G(k+1)-G(k)+4k-4k+4 Φ(2k)= Φ(k)+4 Φ(2k+1)= G(2k+2)-G(2k+1) Φ(2k+1)= G(k+1)+4(k+1)-[G(k+1)+4k+4] Φ(2k+1)= G(k+1)+4k+4-G(k+1)-4k-4 Φ(2k+1)= 0So, it was true. Let's summarize this section:
λ(x)=G(x+1)-P(x) λ(1)=0 λ(2k+1)=0 λ(2k)=2+λ(k) Φ(x)=G(x+1)-G(x) Φ(1)=0 Φ(2k+1)= 0 Φ(2k)=4+Φ(k)
100: int kspace(int a, int b) 101: { 102: int M,a1,b1,Tb, R; 103: if (a<b) { int t; t=a; a=b; b=t; } 104: if (b==1) return 0; 105: M= a/2; 106: a1= a-M; 107: if (b<=M) return a1+b + max2(kspace(M,b), kspace(a1,b)); 108: b1= b-M; 109: Tb= max2(b1,M); 110: R= max3(kspace(M,M), kspace(a1,b1), kspace(a1,Tb)); 111: return R+ 2*(a1+Tb); 112: }Here, if a≥b for the initial call to kspace, then it holds for all recursive calls. Therefore (103) can be done at a higher level, in the code which calls kspace/karatsuba.
In (107), we have two recursive calls:
100: int kspace(int a, int b) 101: { 102: int M,a1,b1,Tb, R; 103: if (b==1) return 0; 104: M= a/2; 105: a1= a-M; 106: if (b<=M) return a1+b + max2(kspace(M,b), kspace(a1,b)); 107: b1= b-M; 108: Tb= max2(b1,M); 109: R= max3( G(M), kspace(a1,b1), kspace(a1,Tb)); 110: return R+ 2*(a1+Tb); 111: }As before, we can split this function into two cases where a is even or odd. While we're doing that, we can also handle the case where a=b separately at the top level.
int K(int a, int b) { if (a==b) return G(a); else if (a%2) return Kodd(a,b); else return Keven(a,b); } Kodd(a=2k+1,b) // a>b, 2k+1>b, 2k≥b { if (b==1) return 0; M= a/2 ⇒ M= k a1= a-M ⇒ a1= k+1 if (b≤M) return a1+b+max2(K(M,b), K(a1,b)); b1= b-M ⇒ b1= b-k Tb= max2(b1,M) ⇒ Tb= max(b-k,k) ⇒ Tb=k (since b-k≤k) R= max(G(M), K(k+1,b-k), K(k+1,Tb)) return R+2*(k+1+Tb); }Simplified further, replacing vars M,a1,b1,and Tb
Kodd(a=2k+1,b) { if (b==1) return 0; if (b≤k) return k+1+b+max2(K(k,b), K(k+1,b)); return max(G(k), K(k+1,b-k), K(k+1,k))+2*(k+1+k); }Since K(k+1,k)= P(k):
Kodd(a=2k+1,b) { if (b==1) return 0; if (b≤k) return k+1+b+max2(K(k,b), K(k+1,b)); return max(G(k), K(k+1,b-k), P(k))+2*(k+1+k); }Also, P(k)≥G(k), so the latter can be removed from the last line:
Kodd(a=2k+1,b): b=1 ⇒ 0 1<b≤k ⇒ k+1+b+max(K(k,b), K(k+1,b)) k<b ⇒ max(K(k+1,b-k), P(k))+4k+2We can do the same things for Keven:
Keven(a=2k, b) // a>b, 2k>b { if (b==1) return 0; M= a/2 ⇒ M= k a1= a-M ⇒ a1= k if (b≤M) return a1+b+max2(K(M,b),K(a1,b)) b1= b-M ⇒ b1= b-k Tb= max2(b1, M) ⇒ Tb= max(b-k,k) = k (since b-k<k) R= max3(G(M),K(a1,b1),K(a1,Tb)) return R+2*(a1+Tb) }Replacing variables, a1=k, M=k, b1=b-k and Tb=k:
Keven(a=2k, b) // a>b, 2k>b { if (b==1) return 0; if (b≤k) return k+b+max2(K(k,b),K(k,b)) return max3(G(k),K(k,b-k),K(k,k))+2*(k+k) }Since K(k,k)=G(k), we can remove it from the last max function. Also, the first max() call has two identical arguments. This call can be replaced with one of the arguments.
Keven(a=2k, b): b=1 ⇒ 0 1<b≤k ⇒ k+b+K(k,b) k<b ⇒ max(G(k),K(k,b-k))+4kSo, the final expression for K is:
K(a,b)= a=b ⇒ G(a) a=2k+1 ⇒ Kodd(a,b) a=2k ⇒ Keven(a,b) Kodd(a=2k+1,b): b=1 ⇒ 0 1<b≤k ⇒ k+1+b+max(K(k,b), K(k+1,b)) k<b ⇒ max(K(k+1,b-k), P(k))+4k+2 Keven(a=2k, b): b=1 ⇒ 0 1<b≤k ⇒ k+b+K(k,b) k<b ⇒ max(G(k),K(k,b-k))+4k
G(a)≥K(a,b) ∀b≤aTo prove this, I can use yet another difference function
δ(a,b)= G(a)-K(a,b) δ(a,b)= G(a) - { a=b ⇒ G(a) a=2k+1 ⇒ Kodd(a,b) a=2k ⇒ Keven(a,b) } δ(a,b)= a=b ⇒ G(a)-G(a) a=2k+1 ⇒ G(a)-Kodd(a,b) a=2k ⇒ G(a)-Keven(a,b) δ(a,b)= a=b ⇒ 0 a=2k+1 ⇒ G(a)-Kodd(a,b) a=2k ⇒ G(a)-Keven(a,b)Let's handle the two cases separately.
δ(2k+1,b)=G(2k+1)-Kodd(2k+1,b) δ(2k+1,b)= G(2k+1) - { b=1 ⇒ 0 1<b≤k ⇒ k+1+b+max(K(k,b), K(k+1,b)) k<b ⇒ max(K(k+1,b-k), P(k))+4k+2 } = b=1 ⇒ G(2k+1)-0 1<b≤k ⇒ G(2k+1)-[k+1+b+max(K(k,b), K(k+1,b))] k<b ⇒ G(2k+1)-[max(K(k+1,b-k), P(k))+4k+2] Replacing the value of G(2k+1) = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ G(k+1)+4k+4-k-1-b-max(K(k,b), K(k+1,b)) k<b ⇒ G(k+1)+4k+4-max(K(k+1,b-k), P(k))-4k-2 = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+G(k+1)-max(K(k,b), K(k+1,b)) k<b ⇒ 2+G(k+1)-max(K(k+1,b-k), P(k)) convert -max(u,v) to +min(-u,-v) = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+G(k+1)+min(-K(k,b),-K(k+1,b)) k<b ⇒ 2+G(k+1)+min(-K(k+1,b-k),-P(k)) move G(k+1) inside min() = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+min(G(k+1)-K(k,b),G(k+1)-K(k+1,b)) k<b ⇒ 2+min(G(k+1)-K(k+1,b-k),G(k+1)-P(k)) replace with known functions = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+min(G(k+1)-K(k,b),δ(k+1,b)) k<b ⇒ 2+min(δ(k+1,b-k),λ(k)) rewrite G(k+1) in terms of G(k) and Φ(k) = b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+min(Φ(k)+G(k)-K(k,b),δ(k+1,b)) k<b ⇒ 2+min(δ(k+1,b-k),λ(k)) δ(2k+1,b)= b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+min(Φ(k)+δ(k,b),δ(k+1,b)) k<b ⇒ 2+min(δ(k+1,b-k),λ(k))We can do the same thing for δ(2k,b)
δ(2k,b)= G(2k)-K(2k,b) = G(2k) - { b=1 ⇒ 0 1<b≤k ⇒ k+b+K(k,b) k<b ⇒ max(G(k),K(k,b-k))+4k } = b=1 ⇒ G(2k)-0 1<b≤k ⇒ G(2k)-[k+b+K(k,b)] k<b ⇒ G(2k)-[max(G(k),K(k,b-k))+4k] expand G(2k) = b=1 ⇒ G(k)+4k 1<b≤k ⇒ G(k)+4k-k-b-K(k,b) k<b ⇒ G(k)+4k-max(G(k),K(k,b-k))-4k = b=1 ⇒ G(k)+4k 1<b≤k ⇒ 3k-b+G(k)-K(k,b) k<b ⇒ G(k)-max(G(k),K(k,b-k)) replace -max(u,v) with +min(-u,-v) = b=1 ⇒ G(k)+4k 1<b≤k ⇒ 3k-b+G(k)-K(k,b) k<b ⇒ G(k)+min(-G(k),-K(k,b-k)) move G(k) inside min() = b=1 ⇒ G(k)+4k 1<b≤k ⇒ 3k-b+G(k)-K(k,b) k<b ⇒ min(G(k)-G(k),G(k)-K(k,b-k)) = b=1 ⇒ G(k)+4k 1<b≤k ⇒ 3k-b+δ(k,b) k<b ⇒ min(0,δ(k,b-k))Let's summarize and also incorporate the case b=a into the two branches of δ
δ(2k+1,b)= b=1 ⇒ G(k+1)+4k+4 1<b≤k ⇒ 3k+3-b+min(Φ(k)+δ(k,b),δ(k+1,b)) k<b<2k+1 ⇒ 2+min(δ(k+1,b-k),λ(k)) b=2k+1 ⇒ 0 δ(2k,b)= b=1 ⇒ G(k)+4k 1<b≤k ⇒ 3k-b+δ(k,b) k<b<2k ⇒ min(0,δ(k,b-k)) b=2k ⇒ 0It's easy to see that δ is never negative. 3k-b is always positive because it's only used in cases where b≤k. The other functions used G, λ and Φ are also non-negative. If we mark the non-negative parts above with ⋆
δ(2k+1,b)= b=1 ⇒ ⋆ 1<b≤k ⇒ ⋆+min(⋆+δ(k,b),δ(k+1,b)) k<b<2k+1 ⇒ ⋆+min(δ(k+1,b-k),⋆) b=2k+1 ⇒ 0 δ(2k,b)= b=1 ⇒ ⋆ 1<b≤k ⇒ ⋆+δ(k,b) k<b<2k ⇒ min(0,δ(k,b-k)) b=2k ⇒ 0The recursion ends at b=2k or b=1, which are both non-negative. In the rest of the cases, we don't have any negative constants and we never subtract a value computed recursively. Therefore, δ can never go below zero. So, this concludes that
G(a) ≥ K(a,b) ∀ b≤aSo, we can use G(a) as an upper bound for K(a,b), making life much more easier.