Longest Increasing Sub sequence - algorithm

Here is the pseudo code for longest increasing sub sequence given on Wikipedia
L = 0
for i = 1, 2, ... n:
binary search for the largest positive j ≤ L
such that X[M[j]] < X[i] (or set j = 0 if no such value exists)
P[i] = M[j]
if j == L or X[i] < X[M[j+1]]:
M[j+1] = i
L = max(L, j+1)
I have understood how the code works. The only thing i cannot understand is the necessity of this statement (if j == L or X[i] < X[M[j+1]]:)
I have tried running the algorithm on many examples and what i could make out is that in all the cases either j == L or X[i] < X[M[j+1]] and so the if statement always evaluates to True. Could you give me an example where the if loop is false and thus required for the algorithm ??

When there are duplicates the if condition will fail
Consider X={2, 2, 2}
if Condition fails when j=0 and L=1

Related

Formulating dp problem [Codeforces 414 B]

all here is the problem statement from an old contest on codeforces
A sequence of l integers b 1, b 2, ..., b l (1 ≤ b 1 ≤ b 2 ≤ ... ≤ b
l ≤ n) is called good if each number divides (without a remainder) by
the next number in the sequence. More formally for all i
(1 ≤ i ≤ l - 1).
Given n and k find the number of good sequences of length k. As the
answer can be rather large print it modulo 1000000007 (109 + 7).
I have formulated my dp[i][j] as the number of good sequences of length i which ends with the jth number, and the transition table as the following pseudocode
dp[k][n] =
for each factor of n as i do
for j from 1 to k - 1
dp[k][n] += dp[j][i]
end
end
But in the editorial it is given as
Lets define dp[i][j] as number of good sequences of length i that ends in j.
Let's denote divisors of j by x1, x2, ..., xl. Then dp[i][j] = sigma dp[i - 1][xr]
But in my understanding, we need two sigmas, one for the divisors and the other for length. Please help me correct my understanding.
My code ->
MOD = 10 ** 9 + 7
N, K = map(int, input().split())
dp = [[0 for _ in range(N + 1)] for _ in range(K + 1)]
for k in range(1, K + 1):
for n in range(1, N + 1):
c = 1
for i in range(1, n):
if n % i != 0:
continue
for j in range(1, k):
c += dp[j][i]
dp[k][n] = c
c = 0
for i in range(1, N + 1):
c = (c + dp[K][i]) % MOD
print(c)
Link to the problem: https://codeforces.com/problemset/problem/414/B
So let's define dp[i][j] as the number of good sequences of length exactly i and which ends with a value j as its last element.
Now, dp[i][j] = Sum(dp[i-1][x]) for all x s.t. x is a divisor of i. Note that x can be equal to j itself.
This is true because if there is some sequence of length i-1 which we have already found that ends with some value x, then we can simply add j to its end and form a new sequence which satisfies all the conditions.
I guess your confusion is with the length. The thing is that since our current length is i, we can add j to the end of a sequence only if its length is i-1, we cannot iterate over other lengths.
Hope this is clear.

How to construct and justify loop invariant, which allows to show partial correctness

I need to construct and justify a loop invariant with given specification:
{n > 0} P {q = | {j: a[j]=x and 0 <= j < n} |}
where |A| is a number of elements of set A. It means that q is equal to the number of elements from array a that are equal to x.
Code P is specified as:
{
int i = 0, q = 0;
while (i != n){
if (a[i] == x)
q = q + 1;
i = i + 1;
}
I know that loop invariant must be true:
before the loop starts
before each iteration of the loop
after the loop terminates
but I have no clue how should I find the right loop invariant, that would allow me to show partial correctness of P afterwards. I already tried to look at every single iteration of the loop and variables for random n, x and a[0...n-1] to see which values combined are constant while the loop is working, but it did not help.
Look at your code carefully. At the beginning, q is 0, and it only grows when you find new elements that are == x. So
q = | {j: a[j]=x and 0 <= j < i} |
is part of your invariant. Note that in your specification, you had < n instead of < i. Notice also that, at loop termination, i == n. So it will also be valid at the start. It will also be true at any point in between: so far, so good. Is anything else missing? Yes, we should also state that
0 <= i <= n -- because that describes the range of values of i (otherwise, i would be free to venture outside the array).
Is this all? Yes -- there is no other loop state left to describe. Therefore, your complete invariant looks like
q = | {j: a[j]=x and 0 <= j < i} | and 0 <= i <= n
When solving these exercises, you can try these 2 steps:
try to describe in plain text what goes on in the algorithm: "I sweep i from 0 to n-1, stopping at n, and at every moment, I keep in q the amount of x that I have found within the array". All variables involved in the loop must be mentioned!.
translate that plain text into math, while also making sure that your post-condition is reflected in the invariant, generally replacing the n by the loop counter (in this case, i)
As a thought experiment, try to write the invariant with the equivalent loop (but iterating from the end to the beginning) instead:
{
int i = n-1, q = 0;
while (i >= 0){
if (a[i] == x)
q = q + 1;
i = i - 1;
}
Mouse over for answer (but try to figure it out first).
q = | {j: a[j]=x and i < j < n} | and -1 <= i < n
Note the different limits, reflecting that i sweeps differently;
but the same overall structure

Why does j = n + 1 in the termination loop invariant of the insertion sort algorithm?

I am currently reading chapter 2 of the TCRC Introduction to Algorithms 3rd edition textbook and I am reading the author's interpretation of the loop invariant of this algorithm. I understand the author's logic for both the initialization and the maintenance. However, the termination is what I am kind of bogged up on. The author claims that at termination, j = n + 1. However, in the pseudocode of the algorithm, j loops from 2 to n. So shouldn't j = n - 1?
EDIT: The book's pseudo-code for insertion sort is:
for j = 2 to A.length
key = A[j]
// Insert A[j] into sorted sequence A[1...j - 1]
i = j - 1
while i > 0 and A[i] > key
A[i + 1] = A[i]
i = i - 1
A[i + 1] = key
EDIT: After reading it carefully, I have finally understood why j = n + 1 during termination. It's because the for loop goes from 2 to n (inclusively), so after j exceeds n, the loop terminates, hence why j = n + 1 at termination. I appreciate the help.
Disclaimer: this can be totally incorrect... It is just a brain spit.
Side note: since j is incremented during this loop, the starting point is irrelevant for the end condition.
for j = 2 to A.length //A.length = n in your question
There is a bit of ambiguity in this pseudo code.
First of all, we assume j is defined outside this for loop and will have an end value when the loop is terminated. see #Dukeling's comment
Second, your code is targeting an array, using the j as indexer: A[j]
The ambiguity exist with the word to in for j = 2 to A.length, is it including or excluding A.length? and there is this indexer A[j]
In common cases, for the indexer in A[j], the valid range for j is [0...A.length -1]
Some languages uses another range, namely: [1...A.length] I think this is intended by the author because A[0] is not being hit at all.
If that's the case.... and the for condition increments j before it breaks the loop (to test the condition and see that it is false), then... you'll get j = A.length + 1.
As a side note:
In common C like languages, arrays have a valid range from [0...A.length -1].
And in this C example, c has the value of A.length after termination:
int c = 0;
for (c = 3; c < A.length; c++)
{
}
//c = A.length after the loop is completed.

Finding Numbers where modulo is k

I have given a Number A where 1<=A<=10^6 and a Number K. I have to find the all the numbers between 1 to A where A%i==k and i is 1<=i<=A. Is there any better solution than looping
Simple Solution
for(int i=1;i<=A;i++)
if(A%i==k) count++;
Is there any better solution than iterating all the numbers between 1 to A
The expression A % i == k is equivalent to A == n * i + k for any integer value of n that gives a value of A within the stated bounds.
This can be rearranged as n * i = A - k, and can be solved by finding all the factors of A - k that are multiples of i (where k < i <= A).
Here are a couple of examples:
A = 100, k = 10
F = factor_list(A-k) = factor_list(90) = [1,2,3,5,6,9,10,15,18,30,45,90]
(discard all factors less than or equal to k)
Result: [15,18,30,45,90]
A = 288, k = 32
F = [2,4,8,16,32,64,128,256]
Result: [64,128,256]
If A - k is prime, then there is either one solution (A-k) or none (if A-k <= k).

halting proof of binary search

l = -1; u = n;
while l+1 != u
m = l + (u-l)/2;
if x[m] < t
l = m;
else
u = m;
p = u;
if p >= n || x[p] != t
p = -1;
We assume x[-1] < t and x[n] >= t and n >= 0 in the above code.
The above code is a modified binary search which can return the first occurrence of the integer t in the integer array x[0..n-1] instead of returning a random one.
My question is like this:
Why do the above code always halt? Can anyone explain it or prove it?
Thanks,
Because on every iteration, the gap between l and u halves, within the constraints of integer arithmetic. All sequences of (positive) integer halving must eventually reach 1, which is the termination condition.

Resources