Is f(n) = 1000n + 4500lgn + 54n O(n)? - math

I was given the following question in my test:
Is f(n) = 1000n + 4500lgn + 54n O(n)?
I answered this question by applying the following definition:
Definition of O(n), which is that for some function f(n) there must be two positive constants, c and k, such that c > 0, k > 0, n >= k, and 0 <= f(n) <= cn. If we can show that constants c and k exist then the function is O(n) (and if those constants don't exist then the function is actually larger than O(n)).
Solution:
0 ≤ 1000n + 4500lgn + 54n ≤ cn
0 ≤ 4000 + 9000 + 216 ≤ 4c when k=4
0 ≤ 3304 ≤ c
0 ≤ 8000 + 13500 + 432 ≤ 8n when n=8>k
0 ≤ 21932 ≤ 8n
0 ≤ 2741.5 ≤ n (last time c=3304 but now it is 2741.5....as n increases, c is not constant!)
Conclusion:
This function is not O(n) - we can't find constant values c and k because they simply don't exist.
Is my solution correct?

0 ≤ 2741.5 ≤ n (last time c=3304 but now it is 2741.5....as n increases, c is not constant!)
The flaw in your solution is that if you stick with the original value of c, the constraint is still satisfied. It is not the actual value of the constants that matters, simply that there exists a pair of constants c and k for which the inequality is satisfied for all n > k.
I don't know what level of rigor is required (by your teachers) in an answer to that question. However, a rigorous solution would require a mathematical proof (from first principles or established theorems) that either c and k do exist1, or that they cannot exist.
1 - A pair of c and k that you can prove does satisfy the constraint for all N > k would be a sufficient proof.

log2n < n, so 1000n + 4500 log2n + 54n ≤ 1000n + 4500n + 54n.
Just add up the coefficients. For k = 1 and c = 1000 + 4500 + 54 = 5554, f(n) ≤ c*n for all n ≥ k. Therefore f is O(n).

Related

How to convert a bitstream to a base20 number?

Given is a bitstream (continuous string of bits too long to be processed at once) and the result should be a matching stream of base20 numbers.
The process is simple for a small number of bits:
Assuming most significant bit right:
110010011 = decimal 403 (1 * 1 + 1 * 2 + 1 * 16 + 1 * 128 + 1 * 256)
403 / 20 = 20 R 3
20 / 20 = 1 R 0
1 / 20 = 0 R 1
Result is [3, 0, 1] = 3 * 1 + 0 * 20 + 1 * 400
But what if the bits are too much to be converted to a decimal number in one step?
My approach was doing both processes in a loop: Convert the bits to decimal and converting the decimal down to base20 numbers. This process requires the multipliers (position values) to be lowered while walking through the bits, because otherwise, they'll quickly increase too much to be calculated probably. The 64th bit would have been multiplied by 2^64 and so on.
note: I understood the question that a bitstream is arriving of unknown length and during an unknown duration and a live conversion from base 2 to base 20 should be made.
I do not believe this can be done in a single go. The problem is that base 20 and base 2 have no common ground and the rules of modular arithmetic do not allow to solve the problem cleanly.
(a+b) mod n = ( (a mod n) + (b mod n) ) mod n
(a*b) mod n = ( (a mod n) * (b mod n) ) mod n
(a^m) mod n = ( (a mod n)^m ) mod n
Now if you have a number A written in base p and q (p < q) as
A = Sum[a[i] p^i, i=0->n] = Sum[b[i] q^i, i=0->n]
Then we know that b[0] = A mod q. However, we do not know A and hence, the above tells us that
b[0] = A mod q = Sum[a[i] p^i, i=0->n] mod q
= Sum[ (a[i] p^i) mod q, i=0->n] mod q
= Sum[ ( (a[i] mod q) (p^i mod q) ) mod q, i=0->n] mod q
This implies that:
If you want to know the lowest digit b0 of a number in base q, you need to have the knowledge of the full number.
This can only be simplified if q = pm as
b[0] = A mod q = Sum[a[i] p^i, i=0->n] mod q
= Sum[ (a[i] p^i) mod q, i=0->n] mod q
= Sum[ a[i] p^i, i=0->m-1]
So in short, since q = 20 and p = 2. I have to say, no, it can not be done in a single pass. Furthermore, remind yourself that I only spoke about the first digit in base q and not yet the ith digit.
As an example, imagine a bit stream of 1000 times 0 followed by a single 1. This resembles the number 21000. The first digit is easy, but to get any other digit ... you are essentially in a rather tough spot.

last digit of a^b^c

I've got stuck on this problem :
Given a, b and c three
natural numbers (such that 1<= a, b, c <= 10^9), you are supposed to find the last digit of the number a^b^c."
What I've firstly thought was the O(log n) algorithm for raising a at power n.
int acc=1; //accumulator
while(n>0) {
if(n%2==1)
acc*=a;
a=a*a;
n/=2;
}
Obviously, some basic math might help, like the "last digit" stuff :
Last_digit(2^n) = Last_digit(2^(n%4))
Where n%4 is the remainder of the division n/4
In a nutshell, I've tried to combine these, but I couldn't get on the good way.
Some help would really be apreciated.
The problem is that b^c may be very large. So you want to reduce it before using the standard modular exponentiation.
You can remark that a^(b^c) MOD 10 can have a maximum of 10 different values.
Because of the pigeonhole principle, there will be a number p such that for some r:
a^r MOD 10 = a^(p+r) MOD 10
p <= 10
r <= 10
This implies that for any q:
a^r MOD 10 = a^r*a^p MOD 10
= (a^r*a^p)*a^p MOD 10
= ...
= a^(r+q*p) MOD 10
For any n = s+r+q*p, with s < p you have:
a^n MOD 10 = a^s*a^(r+q*p) MOD 10
= a^s*a^r MOD 10
= a^((n-r) MOD p)*a^r MOD 10
You can just replace n= (b^c) in the previous equation.
You will only compute (b^c-r) MOD p where p <= 10 which is easily done and then compute a^((b^c-r) MOD p)*a^r MOD 10.
Like I mentioned in my comments, this really doesn't have much to do with smart algorithms. The problem can be reduced completely using some elementary number theory. This will yield an O(1) algorithm.
The Chinese remainder theorem says that if we know some number x modulo 2 and modulo 5, we know it modulo 10. So finding a^b^c modulo 10 can be reduced to finding a^b^c modulo 2 and a^b^c modulo 5. Fermat's little theorem says that for any prime p, if p does not divide a, then a^(p-1) = 1 (mod p), so a^n = a^(n mod (p-1)) (mod p). If p does divide a, then obviously a^n = 0 (mod p) for any n > 0. Note that x^n = x (mod 2) for any n>0, so a^b^c = a (mod 2).
What remains is to find a^b^c mod 5, which reduces to finding b^c mod 4. Unfortunately, we can use neither the Chinese remainder theorem, nor Fermat's little theorem here. However, mod 4 there are only 4 possibilities for b, so we can check them separately. If we start with b = 0 (mod 4) or b = 1 (mod 4), then of course b^c = b (mod 4). If we have b = 2 (mod 4) then it is easily seen that b^c = 2 (mod 4) if c = 1, and b^c = 0 (mod 4) if c > 1. If b = 3 (mod 4) then b^c = 3 if c is even, and b^c = 1 if c is odd. This gives us b^c (mod 4) for any b and c, which then gives us a^b^c (mod 5), all in constant time.
Finally with a^b^c = a (mod 2) we can use the Chinese remainder theorem to find a^b^c (mod 10). This requires a mapping between (x (mod 2), y (mod 5)) and z (mod 10). The Chinese remainder theorem only tells us that this mapping is bijective, it doesn't tell us how to find it. However, there are only 10 options, so this is easily done on a piece of paper or using a little program. Once we find this mapping we simply store it in an array, and we can do the entire calculation in O(1).
By the way, this would be the implementation of my algorithm in python:
# this table only needs to be calculated once
# can also be hard-coded
mod2mod5_to_mod10 = [[0 for i in range(5)] for j in range(2)]
for i in range(10):
mod2mod5_to_mod10[i % 2][i % 5] = i
[a,b,c] = [int(input()) for i in range(3)]
if a % 5 == 0:
abcmod5 = 0
else:
bmod4 = b % 4
if bmod4 == 0 or bmod4 == 1:
bcmod4 = bmod4
elif bmod4 == 2:
if c == 1:
bcmod4 = 2
else:
bcmod4 = 0
else:
if c % 2 == 0:
bcmod4 = 1
else:
bcmod4 = 3
abcmod5 = ((a % 5)**bcmod4) % 5
abcmod2 = a % 2
abcmod10 = mod2mod5_to_mod10[abcmod2][abcmod5]
print(abcmod10)

How can I express this in Big O notation?

How can I express 2(3(logn-1)) in Big O notation?
Is it 2n or 2log n?
This is one case where the basis of the logarithm matters. So lets say, the basis of your logarithm is a. You can change it to base 3 by
logan = log₃n / log₃a
Now you can simplify the exponent
3logan - 1 = 3log₃n / log₃a - 1 = n1/log₃a / 3
So in total you get
2n1/log₃a / 3 = 2n1/log₃a / 3 ⋅ 21/3 ∈ O(2n1/log₃a)
If a = 3 the complexity would be O(2ⁿ). If a = 2, the complexity would be O(2nc), with
c = 1/log₃2 ≈ 1.5850.
Notice: 2nc = 2(nc) ≠ (2n)c = 2cn. So you cannot simplify the complexity more.

O notation: 2^log(O(n^2)) = 2^O(log(n^2))?

I tried to solve this with logarithm rules:
O(n^2) = 2^O(log(n^2))
c*n^2 = 2^log(n^2c)
Im not sure that is true?
No, no, no. You can't just take logarithms.
2^log (O (n^2)) = 2 ^ log (c * n^2)) = c * n^2
2^ O (log n^2) = 2^ (c * log n^2) = (2 ^ (log n^2)) ^ c = (n^2) ^ c.
The first is just O (n^2). The second one is n raised to sum unknown but limited power.
I think this depends on what the equals sign means here. If the equals sign means
"Any function that is of 2log O(n2) is also 2O(log n2)"
Then the claim is true. Let f(n) be some function that's O(n2). This means that there's a c and n0 such that for any n ≥ n0, we know that f(n) ≤ cn2. Therefore, for any n ≥ n0, we know that
2log f(n) ≤ 2log (cn2) = 2(log c + log n2)
The function log c + log n2 is itself O(log n2), so we see that
2log f(n) ≤ 2(log c + log n2) = 2O(log n2)
On the other hand, if the equals sign means
"The class of functions that is 2log O(n2) is the same class of functions that is 2O(log n2)"
then the claim is false. For example, the function n4 is in the second class because it can be written as 22 log n2, but it's not in the first class.
Hope this helps!

How to prove 3n + 2log n = O(n)

How would I be able to prove 3n + 2log n = O(n) using the definition of big-O?
The C is supposedly 6, & the k is 1, but I have no idea how that is found. Much help will greatly be appreciated.
To formally prove this result, you need to find a choice of n0 and c such that
For any n ≥ n0: 3n + 2log n ≤ cn
To start this off, note that if you have any n ≥ 1, then log n < n. Consequently, if you consider any n ≥ 1, you have that
3n + 2log n < 3n + 2n = 5n
Consequently, if you pick n0 = 1 and c = 5, you have that
For any n ≥ n0: 3n + 2log n < 3n + 2n = 5n ≤ cn
And therefore 3n + 2 log n = O(n).
More generally, when given problems like these, try identifying the dominant term (here, the n term) and trying to find some choice of n0 such that the non-dominant terms are overwhelmed by the dominant term. Once you've done this, all that's left to do is choose the right constant c.
Hope this helps!
Wild guess (your question is quite unclear): the task is to show that
O(3n + 2log n) = O(n)
Now that's how it comes out: n -> n grows faster than n -> log n, and since the complexity is asymptotic, only the fastest-growing term matters, which is n in this case.
You can prove the following if I remember correctly:
if f1(n)=O(g1(n)), f2(n)=O(g2(n)) then f1(n)+f2(n)=O(max{g1(n),g2(n)}).
From there it's pretty straight forward.

Resources