How to prove Big O notation - c++

In my algorithm class we are discussing big O notation and I am stuck proving this example problem:
Prove f(n) = 3n lg n + 10n + lg n + 20 = O(n lg n)
Details will be appreciated.

All you need to prove is that for some M and X0:
M n lg n >= 3n lg n +10n + lg n + 20 for all n greater than X0
4 is pretty easy for M
I'm sure you can compute some x0 for which the above inequality holds and then easily show that it remains true for all n greater than X0
It helps to simplify the above after substituting in the 4 to
(n-1)lg n >= 10n + 20
Once any n is big enough, it should be clear that lg n > 1, so any increase in n beyond that increase the right by 1 and the left by more than 1.

Big O notation is an asymptotic notation and it's all about approximation of cases (worst, best and mid one).
In your example, nlgn grows faster than both n and lgn, moreover constant values are not relevant and can be ignored in such an approximation.
Because of that, it follows that the complexity is O(nlgn).

Related

Find euler function of binomial coefficient

I've been trying to solve this problem:
Find Euler's totient function of binomial coefficient C(n, m) = n! / (m! (n - m)!) modulo 10^9 + 7, m <= n < 2 * 10^5.
One of my ideas was that first, we can precalculate the values of phi(i) for all i from 1 to n in linear time, also we can calculate all inverses to numbers from 1 to n modulo 10^9 + 7 using, for example, Fermat's little theorem. After that, we know, that, in general, phi(m * n) = phi(m) * phi(n) * (d / fi(d)), d = gcd(m, n). Because we know that gcd((x - 1)!, x) = 1, if x is prime, 2 if x = 4, and x in all other cases, we can calculate phi(x!) modulo 10^9 + 7 in linear time. However, in the last step, we need to calculate phi(n! / ((m! (n - m)!), (if we already know the function for factorials), so, if we are using this method, we have to know gcd(C(n, m), m! (n - m)!), and I don't know how to find it.
I've also been thinking about factorizing the binomial coefficient, but there seems no efficient way to do this.
Any help would be appreciated.
First, factorize all numbers 1..(2*10^5) as products of prime powers.
Now, factorize n!/k! = n(n-1)(n-2)...(n-k+1) as a product of prime powers by multiplying together the factors of the individual parts. Factorize (n-k)! as a product of prime powers. Subtract the latter powers from the former (to account for the divide).
Now you've got C(n, k) as a product of prime powers. Use the formula phi(N) = N * prod(1 - 1/p for p|N) to calculate phi(C(n, k)), which is straightforward given that you've computed the a list of all the prime powers that divide C(n, k) in the second step.
For example:
phi(C(9, 4)) = 9*8*7*6*5 / 5*4*3*2*1
9*8*7*6*5 = 3*3 * 2*2*2 * 7 * 3*2 * 5 = 7*5*3^3*2^4
5*4*3*2*1 = 5 * 2*2 * 3 * 2 * 1 = 5*3*2^3
9*8*7*6*5/(5*4*3*2*1) = 7*3^2*2
phi(C(9, 4)) = 7*3^2*2 * (1 - 1/7) * (1 - 1/3) * (1 - 1/2) = 36
I've done it in integers rather than integers mod M, but it seems like you already know how division works in the modulo ring.

Efficent Algorithm to Answer Subarray Queries fast

The other day I encountered a problem related with queries, but I can't solve it.
Given an array with N integers and a positive integer M, you must answer Q queries. Each query is characterized as ( i , j ), where i and j are each indices of the array. In each query you must answer how many pairs ( r , s ) exist such that
i <= r <= s <= j
the sum of the array elements with indices in [ r , s ] is divisible by M.
Limits:
N <= 50,000
Q <= 50,000
M <= 100
I have a dynamic programming solution that preprocesses every query ( r , s ) in O( N^2 ), but that is not fast enough. Is there a more efficient solution? I have some ideas with Mo's algorithm, or with segment trees, but I can't get it.
Calculate the prefix sums of the original array (assuming it's 1-based) for every i = 1..N.
The equivalence of Sum[r] and Sum[s] for any two indices r and s where r < s means that the sum of the array elements with indices in [r+1, s] is divisible by M (and we need to calculate the number of such equivalences within interval). The time complexity of this step is O(N).
Precalculate the array Count for every i = 1..N, j = 0..M-1:
Count[i][j] stores the number of times that Sum[len] (where len <= i) was equal to j. Time complexity of this step is O(N*M).
For every query (i, j) the answer will be equal to:
For every possible value of the remainder k we find D(k) - the number of times that Sum[len] is equal to k within interval [i, j]. Then we add to the result the number of all possible pairs of D(k) interval boundaries that is D(k)*(D(k)-1)/2. Time complexity: O(M) for every query.
Complexity: O(N) + O(N*M) + O(Q*M) = O((Q+N)*M), that would be ok for given constraints.
First note that for any subarray (r, s) that sums to a multiple of M:
sum(r, s) == sum(i, s) - sum(i, r - 1)
== (qa * M + ra) - (qb * M + rb)
where ra and rb are both less than M and greater than or equal to 0 (i.e. the respective remainders after dividing by M).
Now sum(r, s) is divisible by M so it's remainder is 0 after dividing by M. Therefore:
ra == rb
If we calculate all the remainders after dividing the sums the subarrays (i, i), (i, i + 1), ... ,(i, j) by M as r1, r2, ... , rj then store the count of all these in an array R of size M so that R[k] is the number of remainders equal to k, then:
R[0] == the number of subarrays starting at i that are divisible by M
and for every k >= 0 and k < M such that R[k] > 1 we can count R[k] choose 2:
(R[k] * (R[k] - 1)) / 2
subarrays not starting at i that are divisible by M.
Creating and summing all these values gives us the answer in O( N + M ) for each (r, s) query.

Sum of series: a^0+2a^1 + 3*a^2 + 4*a^3 + … + n*a^(n-1) (mod M)

Can someone give me an idea of an efficient algorithm for large n which perform O(log(n)) using recursive function not geometric summation formula.
You need to use the formula for sum of geometric progression: a^1 + a^2 + ... a^n = (a^(n+1) - 1) / (a - 1). Using exponentiation by squaring you can compute (a^(n+1) - 1) in O(log(n)). If M is prime dividing by (a - 1) is simply one more exponentiation - for any U coprime with a prime number p, U^(-1) (mod p) = U^(p-2) (mod p). You can prove this using Fermat's little theorem.
First of all, as you state M < 105, you know that all numbers will need at most 16 bits, so provided being just a little cautious, you should not be bothered by precision questions.
Next, as an(mod M) = (a(mod M))n(mod M), you can also say a<M<105
Next if you note un=a0+a1...an-1 (mod M), you can use the following recursions:
u2k = uk+akuk (mod M)
uk+1 = uk+ak (mod M)
u2k+1 = uk+1+ak+1uk (mod M) = uk+ak+a*akuk (mod M)
Given a number n, you will find about log2(n) numbers n, n/2, n/4, ..., 1 and using the above formulas, you can compute easily un/2i and an/2i knowing un/2i+1 and an/2i+1
This algorythm may not be trivial to write (specifically do not forget the mod M operation do make sure not to have overflows) because of different tests, but it is O(log2(n))

calculating complexity of sorting

std::sort performs approximately N*log2(N) (where N is distance) comparisons of elements(source - http://www.cplusplus.com/), so its complexity is N*log2(N).
Please, help me to calculate complexity for the next code:
void func(std::vector<float> & Storage)
{
for(int i = 0; i < Storage.size() - 1; ++i)
{
std::sort(Storage.begin()+i, Storage.end());
Storage[i+1] += Storage[i];
}
}
complexity = N^2*log2(N) or 2log2(2)+3log2(3)+...+(N)log2(N)?
Thank you.
The proper way to compute the complexity is to evaluate the complexity of repeated O(K Log K) problems of linearly increasing sizes K = 1 ... N. This can be done either by computing the sum, or by just computing the integral
Integrate[K Log[K], {K, 0, N}]
with e.g. Mathematica, and you get
1/4 N^2 (-1 + 2 Log[N])
which is of O(N^2 Log N).
Even though for polynomial and logarithmic functions it holds true, in general it is not true that the integral of K = 1 ... N subproblems of complexity f(K) is equal to N f(N). E.g. the sum of K = 1 ... N subproblems of complexity Exp[K] is simply Exp[N], not N Exp[N].
I would agree with N^2*log2(N) as the sort algorithm is run N times. In Big-O, where c is a constant:
c*N * N*log2(N) => O(N^2*log2(N))
It will be asymptotically O((N^2)*(log2(N))
we need sum of k*log2(k) k from 1 to N
You are summing up logarithmic functions:
complexity <- 0
for i = 1..N
complexity += i Log(i)
Resulting in the summation:
Log(1) + 2 Log(2) + ... + N Log(N)
from http://en.wikipedia.org/wiki/Logarithm:
the logarithm of a product is the sum of the logarithms of the factors:
thus:
the summation becomes:
Log(1) + Log(2^2) + .. + Log(N^N)
further simplifying:
Log(1*2^2*3^3*...*N^N)

How can we compute N choose K modulus a prime number without overflow?

How can we computer (N choose K)% M in C or C++ without invoking overflow ?
For the particular case when N (4<=N<=1000) and K (1<=K<=N) and M = 1000003.
To compute (n choose k) % M, you can separately compute the nominator (n!) modulus M and the denominator (k!*(n - k)!) modulus M and then multiply the nominator by the denominator's modular multiplicative inverse (in M). Since M is prime, you can use Fermat's Little Theorem to calculate the multiplicative inverse.
There is a nice explanation, with sample code, on the following link (problem SuperSum):
http://www.topcoder.com/wiki/display/tc/SRM+467
Since 1000000003 = 23 * 307 * 141623 you can calculate (n choses k) mod 23, 307 and 141623 and then apply the chinese reminder theorem[1]. When calculating n!, k! and (n-k)!, you should calculate everythinng mod 23, 307 and 141623 each step to prevent overflow.
In this way you should avoid overflow even in 32bit machines.
A little improvement would be to calculate (n choses k) mod 141623 and 7061 (23 * 307) (edit: but it can be a little tricky to calculate the inverse modulus 7061, so I wouldn't do this)
I'm sorry for my poor English.
[1]http://en.wikipedia.org/wiki/Chinese_remainder_theorem
Edit2: Another potentially problem I've found is when calculating n! mod 23 (for example) it will probably be 0, but that doesn't implies that (n choses k) is 0 mod 23, so you should count how many times 23 divides n!, (n-k)! and k! before calculating (n choses k). Calculating this is easy, p divides n! exactly floor(n/p) + floor(n/p²) + ... times. If it happens that 23 divides n! the same times it divides k! and (n-k)!, the you proceed to calculate (n choses k) mod 23 dividing by 23 every multipler of it every time.The same applies for 307, but not for 141623
You could use the recursive formula from the link you gave and do the calculation mod M.
Here is a simple example:
(A * B * C) % N ... is equal to... ((A % N) * (B % N) * (C % N)) % N;
That is, all you need to apply modulus to every operand and product, or as soon as it becomes big a number. And last the modulus must apply to the overall result.
Use Stirling's approximation to calculate the binomial coefficient. Then just calculate the modulus as usual.