Reputation: 105
Here is a question from previous HackerEarth Challenge -
Roy has a matrix of size NxN. Rows and Columns are numbered from 1 to N. jth column of ith row contains integer division i/j.
In other words, Matrix[i][j] = int(i/j) where 1 ≤ i, j ≤ N.
Your task is to find sum of this matrix i.e.
sum = 0
for i=1 to N-1
for j=1 to N-1
sum += Matrix[i][j]
Constraints:
1 ≤ T ≤ 10
1 ≤ N ≤ 1000000
and here is my solution to this problem
#include <cstdio>
#include <cassert>
using namespace std;
#define MAXT 10
#define MAXN 1000000
long long solve(long long N){
long long ans = 0;
for(int i=1;i<N-1;i++)
{
for(int j=1; j<N-1 ; j++)
{
int temp = N*i/j;
ans = ans + temp;
}
}
return ans;
}
int main(){
int T, N;
scanf("%d", &T);
assert(T>0 and T<=MAXT);
while(T--){
scanf("%d", &N);
assert(N>0 and N<=MAXN);
printf("%lld\n", solve((long long)N));
}
return 0;
}
But the output of this program is not coming correct.
So please tell me if I have achieved things here correctly. If yes what else can I do to optimize this code. Thanks for your help.
Upvotes: 0
Views: 738
Reputation: 6407
Pay attention on for
-loop condition
for i=1 to N-1 // in pseudo code
should be
for(int i=1;i < N;i++)
or
for(int i=1;i <= N-1;i++)
But NOT for(int i=1;i < N-1;i++)
(that option loses the last item).
Next, expressions like i/j
with integers are integer division that has only integer part of result (without rounding). This will lead to 0
value if i < j
.
And the last one, summarizing expression should be (from sum += Matrix[i][j]
) as
ans += Matrix[i][j];
BUT where is your matrix?
UPDATE
If for same reasons, you use expression N*i/j
instead of values from matrix (Matrix[i][j]
), and you defensively want to use integer arithmetic you can minimize the code as:
long long solve(long long N){
long long ans = 0;
for (int i = 1; i < N; i++)
{
for (int j = 1; j < N; j++)
{
ans += N * i / j;
}
}
return ans;
}
at the same time you should understand that long long
cannot save you from arithmetic overflow when N > 1000000
UPDATE 2:
Check the task about 1 ≤ i, j ≤ N
and if it is really <= N try changes for both for
as
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= i; j++)
{
ans += i / j;
}
}
Upvotes: 1
Reputation: 8614
Note that int(i/j)
does not change much for larger values of j
i.e. if j = 1000
int(i/j)
will be 0
for 1-1000
, then it will be 1
for 1000-2000
, and so on. Using this fact, you can create an algorithm with much lower complexity.
e.g. if N = 50000
, then for j = 1000
, you will get 0... (1000)
times + 1 ..(1000)
times + 2..(1000)
times.... upto 49,000/1000... (1000)
times.
i.e. div = N/j
ans += (div *(div-1) *j)
You also need to make a correction if N/j
is not a whole number as shown in the code below.
long long solve(long long N){
long long ans = 0;
long long div, mod;
for (int i = 1; i <= N; i++)
{
div = N/i;
mod = i- N%i;
ans += (div * (div+1) * i)/2;
// For the case when N does not go directly into i,
// e.g. N = 47500, i = 1000, the last 500 need to be removed from the sum
ans -= (mod-1) * div;
printf ("\n i = %d, ans = %lld",i,ans);
}
return ans;
}
This is O(n) complexity.
Edit: Corrected to fix expected results.
Upvotes: 6
Reputation: 2259
From Complexity point of view:
int x = int(i/j)
means x > 0
only when i >= j
. So you can avoid many unnecessary additions and divisions.
That is, if Matrix[i][j] = int(i/j); then Matrix[i][j] = 0; for (i < j)
Therefore, the for
loops should be:
for i=1 to N-1
for j=1 to i
sum += Matrix[i][j];
UPDATE 1: After OP upated the question with sample output, it seems that the for loop
for i
should run till N
. Modified Code as follow:
for(i = 1; i <= N; ++i)
for(j = 1; j <= i; ++j)
sum += (int)(i/j);
Upvotes: 1
Reputation: 5238
First column is 1, 2, 3, 4, 5, ...
.
Second column is 0, 1, 1, 2, 2, 3, 3, 4, 4, ...
.
Third columns is 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, ...
.
Then derive formula to calculate sum of column without loop in O(1) using arithmetic progression sum formula and accurately calculating what is at the beginning and the end of each column. Then iterate over columns. This will give you O(n) solution which fits given constraints.
Upvotes: 1