x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
I'm trying to predict the value of x by capturing a summation but I'm kind of stuck because I know that for each iteration of the first for loop, the summation changes for the inner loop. For example if we assume x is 10, after the first completion of the inner loop, x would have 9, then after the 2nd completion, we add 8 to x, then 7, 6, etc. The final value of x would be 35. How would I represent this in a cohesive equation for any positive even integer n?
Skip to the end for a simple equation; here I show the steps you might take.
First, here's the original code:
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
We can start j at i+1 to skip a lot of pointless loops
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = i+1; j <=n; j++) {
if (j > i)
x++;
}
}
Then instead of adding 1 on each of n-i loops, we can just add n-i.
x = 0;
for (i = 1; i <= n/2; i++) {
x += (n-i)
}
That's the same as this (just writing out what we're adding in the loops):
x = (n-1) + (n-2) + ... + (n - n/2)
We can pull out the n's.
x = n * (n/2) - 1 - 2 - 3 - ... - n/2
The final simplification is for the summation of 1 through n/2.
x = n * (n/2) - ((n/2) * (n/2 + 1))/2
I have to find the order of matrix formed after matrix chain multiplication.
I have the following code to determine the minimum number of multiplications required to multiply all matrices:
ll MatrixChainOrder(ll p[], ll n) {
ll m[n][n], i, j, k, L, q;
for(i = 1; i < n; i++) {
m[i][i] = 0;
}
for(L = 2; L < n; L++) {
for(i = 1; i < n - L + 1; i++) {
j = i + L - 1;
m[i][j] = INT_MAX;
for(k = i; k <= j - 1; k++) {
q = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
}
}
}
}
return m[1][n-1];
}
How can I print the order of the matrix as well? Can anyone explain?
You need to use another auxiliary matrix (s for example), with indices.
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
With matrices m and s you can print recursively the best matrix parenthesization.
There are n numbers, ranging 1-100. n ranges in 1-1000.
Another number k. Its bounds are 1 <= k <= 10^6
How to check if its possible to divide the given n numbers in two sets such that the sum of both group numbers is <=k.
I am looking for a high level implementation approach or an algorithm which will return true if the division is possible.
A DP based solution with a complexity of O(n*sum)
for (int i = 0; i < n; i++) {
sum += a[i];
}
int[][] dp = new int[n + 1][sum + 1];
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <= sum; j++) {
dp[i + 1][j] = dp[i][j];
if (a[i] <= j) {
dp[i + 1][j] |= dp[i][j - a[i]];
}
}
}
for (int i = sum / 2; i >= 0; i--) {
if (dp[n][i] == 1) {
int x = sum - i;
if (x > k || i > k) {
System.out.println("NO");
} else {
System.out.println("YES");
}
break;
}
}
I am looking for an algorithm that expresses a given number as a sum of (up to) four squares.
Examples
120 = 82 + 62 + 42 + 22
6 = 02 + 12 + 12 + 22
20 = 42 + 22 + 02+ 02
My approach
Take the square root and repeat this repeatedly for the remainder:
while (count != 4) {
root = (int) Math.sqrt(N)
N -= root * root
count++
}
But this fails when N is 23, even though there is a solution:
32 + 32+ 22 + 12
Question
Is there any other algorithm to do that?
Is it always possible?
###Always possible?
Yes, the Lagrange's four square theorem states that:
every natural number can be represented as the sum of four integer squares.
It has been proved in several ways.
###Algorithm
There are some smarter algorithms, but I would suggest the following algorithm:
Factorise the number into prime factors. They don't have to be prime, but the smaller they are, the better: so primes are best. Then solve the task for each of these factors as below, and combine any resulting 4 squares with the previously found 4 squares with the Euler's four-square identity.
(a2 + b2 + c2 + d2)
(A2 + B2 + C2 + D2) =
(aA + bB + cC + dD)2 +
(aB − bA + cD − dC)2 +
(aC − bD − cA + dB)2 +
(aD + bC − cB − dA)2
Given a number n (one of the factors mentioned above), get the greatest square that is not greater than n, and see if n minus this square can be written as the sum of three squares using the Legendre's three-square theorem: it is possible, if and only when this number is NOT of the following form:
4a(8b+7)
If this square is not found suitable, try the next smaller one, ... until you find one. It guaranteed there will be one, and most are found within a few retries.
Try to find an actual second square term in the same way as in step 1, but now test its viability using Fermat's theorem on sums of two squares which in extension means that:
if all the prime factors of n congruent to 3 modulo 4 occur to an even exponent, then n is expressible as a sum of two squares. The converse also holds.
If this square is not found suitable, try the next smaller one, ... until you find one. It's guaranteed there will be one.
Now we have a remainder after subtracting two squares. Try subtracting a third square until that yields another square, which means we have a solution. This step can be improved by first factoring out the largest square divisor. Then when the two square terms are identified, each can then be multiplied again by the square root of that square divisor.
This is roughly the idea. For finding prime factors there are several solutions. Below I will just use the Sieve of Eratosthenes.
This is JavaScript code, so you can run it immediately -- it will produce a random number as input and display it as the sum of four squares:
function divisor(n, factor) {
var divisor = 1;
while (n % factor == 0) {
n = n / factor;
divisor = divisor * factor;
}
return divisor;
}
function getPrimesUntil(n) {
// Prime sieve algorithm
var range = Math.floor(Math.sqrt(n)) + 1;
var isPrime = Array(n).fill(1);
var primes = [2];
for (var m = 3; m < range; m += 2) {
if (isPrime[m]) {
primes.push(m);
for (var k = m * m; k <= n; k += m) {
isPrime[k] = 0;
}
}
}
for (var m = range + 1 - (range % 2); m <= n; m += 2) {
if (isPrime[m]) primes.push(m);
}
return {
primes: primes,
factorize: function (n) {
var p, count, primeFactors;
// Trial division algorithm
if (n < 2) return [];
primeFactors = [];
for (p of this.primes) {
count = 0;
while (n % p == 0) {
count++;
n /= p;
}
if (count) primeFactors.push({value: p, count: count});
}
if (n > 1) {
primeFactors.push({value: n, count: 1});
}
return primeFactors;
}
}
}
function squareTerms4(n) {
var n1, n2, n3, n4, sq, sq1, sq2, sq3, sq4, primes, factors, f, f3, factors3, ok,
res1, res2, res3, res4;
primes = getPrimesUntil(n);
factors = primes.factorize(n);
res1 = n > 0 ? 1 : 0;
res2 = res3 = res4 = 0;
for (f of factors) { // For each of the factors:
n1 = f.value;
// 1. Find a suitable first square
for (sq1 = Math.floor(Math.sqrt(n1)); sq1>0; sq1--) {
n2 = n1 - sq1*sq1;
// A number can be written as a sum of three squares
// <==> it is NOT of the form 4^a(8b+7)
if ( (n2 / divisor(n2, 4)) % 8 !== 7 ) break; // found a possibility
}
// 2. Find a suitable second square
for (sq2 = Math.floor(Math.sqrt(n2)); sq2>0; sq2--) {
n3 = n2 - sq2*sq2;
// A number can be written as a sum of two squares
// <==> all its prime factors of the form 4a+3 have an even exponent
factors3 = primes.factorize(n3);
ok = true;
for (f3 of factors3) {
ok = (f3.value % 4 != 3) || (f3.count % 2 == 0);
if (!ok) break;
}
if (ok) break;
}
// To save time: extract the largest square divisor from the previous factorisation:
sq = 1;
for (f3 of factors3) {
sq *= Math.pow(f3.value, (f3.count - f3.count % 2) / 2);
f3.count = f3.count % 2;
}
n3 /= sq*sq;
// 3. Find a suitable third square
sq4 = 0;
// b. Find square for the remaining value:
for (sq3 = Math.floor(Math.sqrt(n3)); sq3>0; sq3--) {
n4 = n3 - sq3*sq3;
// See if this yields a sum of two squares:
sq4 = Math.floor(Math.sqrt(n4));
if (n4 == sq4*sq4) break; // YES!
}
// Incorporate the square divisor back into the step-3 result:
sq3 *= sq;
sq4 *= sq;
// 4. Merge this quadruple of squares with any previous
// quadruple we had, using the Euler square identity:
while (f.count--) {
[res1, res2, res3, res4] = [
Math.abs(res1*sq1 + res2*sq2 + res3*sq3 + res4*sq4),
Math.abs(res1*sq2 - res2*sq1 + res3*sq4 - res4*sq3),
Math.abs(res1*sq3 - res2*sq4 - res3*sq1 + res4*sq2),
Math.abs(res1*sq4 + res2*sq3 - res3*sq2 - res4*sq1)
];
}
}
// Return the 4 squares in descending order (for convenience):
return [res1, res2, res3, res4].sort( (a,b) => b-a );
}
// Produce the result for some random input number
var n = Math.floor(Math.random() * 1000000);
var solution = squareTerms4(n);
// Perform the sum of squares to see it is correct:
var check = solution.reduce( (a,b) => a+b*b, 0 );
if (check !== n) throw "FAILURE: difference " + n + " - " + check;
// Print the result
console.log(n + ' = ' + solution.map( x => x+'²' ).join(' + '));
The article by by Michael Barr on the subject probably represents a more time-efficient method, but the text is more intended as a proof than an algorithm. However, if you need more time-efficiency you could consider that, together with a more efficient factorisation algorithm.
It's always possible -- it's a theorem in number theory called "Lagrange's four square theorem."
To solve it efficiently: the paper Randomized algorithms in number theory (Rabin, Shallit) gives a method that runs in expected O((log n)^2) time.
There is interesting discussion about the implementation here: https://math.stackexchange.com/questions/483101/rabin-and-shallit-algorithm
Found via Wikipedia:Langrange's four square theorem.
Here is solution , Simple 4 loops
max = square_root(N)
for(int i=0;i<=max;i++)
for(int j=0;j<=max;j++)
for(int k=0;k<=max;k++)
for(int l=0;l<=max;l++)
if(i*i+j*j+k*k+l*l==N){
found
break;
}
So you can test for any numbers. You can use break condition after two loops if sum exceeds then break it.
const fourSquares = (n) => {
const result = [];
for (let i = 0; i <= n; i++) {
for (let j = 0; j <= n; j++) {
for (let k = 0; k <= n; k++) {
for (let l = 0; l <= n; l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
It's running too long
const fourSquares = (n) => {
const result = [];
for (let i = 0; i <= n; i++) {
for (let j = 0; j <= (n - i * i); j++) {
for (let k = 0; k <= (n - i * i - j * j); k++) {
for (let l = 0; l <= (n - i * i - j * j - k * k); l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
const fourSquares = (n) => {
const result = [];
for (let i = 0; i * i <= n; i++) {
for (let j = 0; j * j <= n; j++) {
for (let k = 0; k * k <= n; k++) {
for (let l = 0; l * l <= n; l++) {
if (i * i + j * j + k * k + l * l === n) {
result.push(i, j, k, l);
return result;
}
}
}
}
}
return result;
}
const fourSquares = (n) => {
let a = Math.sqrt(n);
let b = Math.sqrt(n - a * a);
let c = Math.sqrt(n - a * a - b * b);
let d = Math.sqrt(n - a * a - b * b - c * c);
if (n === a * a + b * b + c * c + d * d) {
return [a, b, c, d];
}
}
I am sure the running time of this nested loop is O(N*log(N)). The running time of the inner loop is log(N) and the outher loop is N.
for (int i = 0; i < N; ++i) {
for (int j = 1; j <= i; j *= 2) {
}
}
In the inner Loop what if I change j *= 2 to j *= 3. How is the result going to change in this case?
#Kevin is completely right, but I thought I would show some experimental results. You can easily test this out by creating a counter that gets incremented inside each inner loop iteration and running for different values of N. Then a fit can be made of the form time = a * N * log(N). For the case j *= 2, we get a coefficient a = 1.28. For j *= 3, we get a = 0.839.
I generated this figure using the MATLAB script below:
clear
clc
close all
nmin = 10;
nmax = 1000;
count1 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 2;
k = k + 1;
end
end
count1(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
figure
hold on
plot(ns, count1, '--')
a1 = mean(count1 ./ (ns .* log(ns)))
fit1 = a1 * ns .* log(ns);
plot(ns, fit1)
%%
count2 = zeros(nmax - nmin + 1, 1);
for n = nmin: nmax
k = 0;
for i = 0: n - 1
j = 1;
while (j <= i)
j = j * 3;
k = k + 1;
end
end
count2(n - nmin + 1) = k;
end
ns = (nmin: nmax)';
plot(ns, count2, '-.')
a2 = mean(count2 ./ (ns .* log(ns)))
fit2 = a2 * ns .* log(ns);
plot(ns, fit2)
xlabel('N')
ylabel('Time complexity')
legend('j *= 2', 'j *= 2 fit', 'j *= 3', 'j *= 3 fit', 'Location', 'NorthWest')
It will still be logarithmic. However, it will be scaled by a constant factor (which is irrelevant in Big O analysis).
The effect is that the base of the logarithm changes (see https://en.wikipedia.org/wiki/Logarithm#Change_of_base).
----------[ j = 2 * j ] for j < i:-------------
j = 2*1 = 2 =>2^1
2*2 = 4 =>2^2
2*4 = 8 =>2^3
............. 2^k = n say n==i
if log applied on both side 2^k = n
log(2^k) = logn
k = log_2(N) where 2 is the base
----------[ j = 3 * j ] for j < i:-------------
j = 3*1 = 3 =>3^1
3*3 = 9 =>3^2
3*9 = 27 =>2^3
.............loop stop when 3^k = n say n==i
if log applied on both side 3^k = n
log(3^k) = logn
k = log_3(N) where 3 is the base