Finding all pairs of numbers that equals an equation - c++

What would be the most optimal method in c++ to discover all pairs of positive integer numbers that fit a formula. For example:
a^2 * b = 16;//a & b MUST be positive INT.
How could I find all the combinations of a and b that will fit the formula?
Edit: For more clarity, this is just an example. Really I have a^2 * b = c where c is incrementing using a for loop and I need to find every positive integer pair (a,b) that will fit the criteria of this equation.

The problem is to find all pairs of positive integers (a,b) that satisfy the equation a^2 * b = c where c is also a positive integer.
From the equation, c is divisible by a perfect square. So first, we find all perfect squares that divide c evenly. Trivially, a=1, b=c satisfies this, so we know that every value of c has at least one solution. After finding every a, we divide c by each of the a^2 to yield its corresponding b.
Here's the above implemented in C++:
std::vector<std::pair<int, int> > solve(int c) {
std::vector<int> a;
for (int i = 1; i * i <= c; ++i)
if (c % (i*i) == 0) a.push_back(i);
std::vector<std::pair<int, int> > solutions;
solutions.reserve(a.size());
for (std::vector<int>::iterator it = a.begin(); it != a.end(); ++it) {
const int& a = *it;
solutions.push_back(std::pair<int, int>(a, c / (a*a)));
}
return solutions;
}
Here's a live example, showing solutions for c = 7! = 5040.

Find the factors of c and then find the subset that use three values, two of which are the same.

By inspection, the three integer solutions are:
a = ±1, b = 16
a = ±2, b = 4
a = ±4, b = 1
Otherwise, there are infinite solutions. Wolfram|Alpha gives the details.

If you need to do this repeatedly, this is what I think the most efficient way to solve this problem:
1. Setup a square table, [0, 1, 4, 9, 16, ......], the length of the table depends on the maximum number you are going to deal with, anyway, you will need O(sqrt(N)) space for the lookup table.
2. divide the number into factors, for example, 16 has 5 factors (1, 2, 4, 8, 16).
3. from checking lookup table, you can find 1, 4, and 16 are in the lookup table. so there are 6 pairs, namingly, (-1 or 1)^2 * 16, (-2 or 2)^2 * 4, and (-4 or 4)^2 * 1.

Related

Is there any number repeated in the array?

There's array of size n. The values can be between 0 and (n-1) as the indices.
For example: array[4] = {0, 2, 1, 3}
I should say if there's any number that is repeated more than 1 time.
For example: array[5] = {3,4,1,2,4} -> return true because 4 is repeated.
This question has so many different solutions and I would like to know if this specific solution is alright (if yes, please prove, else refute).
My solution (let's look at the next example):
array: indices 0 1 2 3 4
values 3 4 1 2 0
So I suggest:
count the sum of the indices (4x5 / 2 = 10) and check that the values' sum (3+4+1+2+0) is equal to this sum. if not, there's repeated number.
in addition to the first condition, get the multiplication of the indices(except 0. so: 1x2x3x4) and check if it's equal to the values' multiplication (except 0, so: 3x4x1x2x0).
=> if in each condition, it's equal then I say that there is NO repeated number. otherwise, there IS a repeated number.
Is it correct? if yes, please prove it or show me a link. else, please refute it.
Why your algorithm is wrong?
Your solution is wrong, here is a counter example (there may be simpler ones, but I found this one quite quickly):
int arr[13] = {1, 1, 2, 3, 4, 10, 6, 7, 8, 9, 10, 11, 6};
The sum is 78, and the product is 479001600, if you take the normal array of size 13:
int arr[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
It also has a sum of 78 and a product of 479001600 so your algorithm does not work.
How to find counter examples?1
To find a counter example2 3:
Take an array from 0 to N - 1;
Pick two even numbers3 M1 > 2 and M2 > 2 between 0 and N - 1 and halve them;
Replace P1 = M1/2 - 1 by 2 * P1 and P2 = M2/2 + 1 by 2 * P2.
In the original array you have:
Product = M1 * P1 * M2 * P2
Sum = 0 + M1 + P1 + M2 + P2
= M1 + M1/2 - 1 + M2 + M2/2 + 1
= 3/2 * (M1 + M2)
In the new array you have:
Product = M1/2 * 2 * P1 + M2/2 * 2 * P2
= M1 * P1 * M2 * P2
Sum = M1/2 + 2P1 + M2/2 + 2P2
= M1/2 + 2(M1/2 - 1) + M2/2 + 2(M2/2 + 1)
= 3/2 * M1 - 2 + 3/2 * M2 + 2
= 3/2 * (M1 + M2)
So both array have the same sum and product, but one has repeated values, so your algorithm does not work.
1 This is one method of finding counter examples, there may be others (there are probably others).
2 This is not exactly the same method I used to find the first counter example - In the original method, I used only one number M and was using the fact that you can replace 0 by 1 without changing the product, but I propose a more general method here in order to avoid argument such as "But I can add a check for 0 in my algorithm.".
3 That method does not work with small array because you need to find 2 even numbers M1 > 2 and M2 > 2 such that M1/2 != M2 (and reciprocally) and M1/2 - 1 != M2/2 + 1, which (I think) is not possible for any array with a size lower than 14.
What algorithms do work?4
Algorithm 1: O(n) time and space complexity.
If you can allocate a new array of size N, then:
template <std::size_t N>
bool has_repetition (std::array<int, N> const& array) {
std::array<bool, N> rep = {0};
for (auto v: array) {
if (rep[v]) {
return true;
}
rep[v] = true;
}
return false;
}
Algorithm 2: O(nlog(n)) time complexity and O(1) space complexity, with a mutable array.
You can simply sort the array:
template <std::size_t N>
bool has_repetition (std::array<int, N> &array) {
std::sort(std::begin(array), std::end(array));
auto it = std::begin(array);
auto ne = std::next(it);
while (ne != std::end(array)) {
if (*ne == *it) {
return true;
}
++it; ++ne;
}
return false;
}
Algorithm 3: O(n^2) time complexity and O(1) space complexity, with non mutable array.
template <std::size_t N>
bool has_repetition (std::array<int, N> const& array) {
for (auto it = std::begin(array); it != std::end(array); ++it) {
for (auto jt = std::next(it); jt != std::end(array); ++jt) {
if (*it == *jt) {
return true;
}
}
}
return false;
}
4 These algorithms do work, but there may exist other ones that performs better - These are only the simplest ones I could think of given some "restrictions".
What's wrong with your method?
Your method computes some statistics of the data and compares them with those expected for a permutation (= correct answers). While a violation of any of these comparisons is conclusive (the data cannot satisfy the constraint), the inverse is not necessarily the case. You only look at two statistics, and these are too few for sufficiently large data sets. Owing to the fact that the data are integer, the smallest number of data for which your method may fail is larger than 3.
If you are searching duplicates in your array there is simple way:
int N =5;
int array[N] = {1,2,3,4,4};
for (int i = 0; i< N; i++){
for (int j =i+1; j<N; j++){
if(array[j]==array[i]){
std::cout<<"DUPLICATE FOUND\n";
return true;
}
}
}
return false;
Other simple way to find duplicates is using the std::set container for example:
std::set<int> set_int;
set_int.insert(5);
set_int.insert(5);
set_int.insert(4);
set_int.insert(4);
set_int.insert(5);
std::cout<<"\nsize "<<set_int.size();
the output will be 2, because there is 2 individual values
A more in depth explanation why your algorithm is wrong:
count the sum of the indices (4x5 / 2 = 10) and check that the values' sum (3+4+1+2+0) is equal to this sum. if not, there's repeated number.
Given any array A which has no duplicates, it is easy to create an array that meets your first requirement but now contains duplicates. Just take take two values and subtract one of them by some value v and add that value to the other one. Or take multiple values and make sure the sum of them stays the same. (As long as new values are still within the 0 .. N-1 range.) For N = 3 it is already possible to change {0,1,2} to {1,1,1}. For an array of size 3, there are 7 compositions that have correct sum, but 1 is a false positive. For an array of size 4 there are 20 out of 44 have duplicates, for an array of size 5 that's 261 out of 381, for an array of size 6 that's 3612 out of 4332, and so on. It is save to say that the number of false positives grows much faster than real positives.
in addition to the first condition, get the multiplication of the indices(except 0. so: 1x2x3x4) and check if it's equal to the values' multiplication (except 0, so: 3x4x1x2x0).
The second requirement involves the multiplication of all indices above 0. It is easy to realize this is could never be a very strong restriction either. As soon as one of the indices is not prime, the product of all indices is no longer uniquely tied to the multiplicands and a list can be constructed of different values with the same result. E.g. a pair of 2 and 6 can be replaced with 3 and 4, 2 and 9 can be replaced with 6 and 3 and so on. Obviously the number of false positives increases as the array-size gets larger and more non-prime values are used as multiplicands.
None of these requirements is really strong and the cannot compensate for the other. Since 0 is not even considered for the second restriction a false positive can be created fairly easy for arrays starting at size 5. any pair of 0 and 4 can simply be replaced with two 2's in any unique array, for example {2, 1, 2, 3, 2}
What you would need, is to have a result that is uniquely tight to the occurring values. You could tweak your second requirement to a more complex approach and skip over the non-prime values and take 0 into account. For example you could use the first prime as multiplicand (2) for 0, use 3 as multiplicand for 1, 5 as multiplicand for 2, and so on. That would work (you would not need the first requirement), but this approach would be overly complex. An simpler way to get a unique result would be to OR the i-th bit for each value (0 => 1 << 0, 1 => 1 << 1, 2 => 1 << 2, and so on. (Obviously it is faster to check wether a bit was already set by a reoccurring value, rather than wait for the final result. And this is conceptually the same as using a bool array/vector from the other examples!)

Faster algorithm to count how many numbers are divisible by a specific integer in a range

int a,b,c,d=0;
cin>>a>>b>>c;
for (int i=a;i<=b;i++)
{
if (i%c==0){d++;}
}
cout<<d;
So this is the code, a..b is the number range, c is the divisor, and d counts the multiples of c. For example when a=5, b=15, c=3, d equals 4, because "6, 9, 12, 15" are the multiples between 5 and 15.
I need to find faster way to do this, can anyone help?
One way is to do it like this (no loops required):
int lower = (a + c - 1) / c; // find lowest divisor (round up)
int upper = b / c; // find higher divisor (round down)
d = upper - lower + 1; // get no of divisors
For your example case, lower will be 2, upper will be 5, giving d equal to 4.
Rather than checking every number within the range you could something like this.
Find number of divisors within the maximum number and then within minimum number. After subtraction you would get desired result. For e.g:-
Let's say range is [5,15].
15/3 = 5; //within max number.
5/3 = 1; //within min number.
result = 5-1 = 4;
NOTE:- You have to take care of boundaries in the range to get correct result.
An untested off-the-top-of-my-head algorithm to find all the proper divisors of a positive integer...
Let the number you want to find the divisors for be N.
Let i = 2
If N % i == 0, then you have two divisors: i and N/i. Add these to the list (or count) of divisors
If i > sqrt(N), finish, else set i = i + 1 and go to (2)
For example, if N = 24, then this would give you
i = 2 => 2, 12
i = 3 => 3, 8
i = 4 => 4, 6
sqrt(24) = 4.90, so finish
(I know this algorithm doesn't strictly match what you asked, but it should be easy enough to adapt.)

find triangular triplet in an array [duplicate]

zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)

finding triangulars from array

zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)

PROJECT EULER #29

Well, after solving this problem by naive STL set,I was reading the forum entries,there I find this entry :
#include <iostream>
#include <cmath>
#define MAX 100
using namespace std;
int main(){
int res=(MAX-1)*(MAX-1);
for(int i=2;i<MAX;i++)
for(int j=i*i;j<=MAX;j=j*i)
res = res-int(MAX*(log(i)/log(j)))+1;
cout<<res<<endl;
return 0;
}
The author's explanation :
Maximum will be 99*99. I subtracted occurrences of those numbers which are powers of some lower numbers (2-100): -
For example: -
4^2,4^3,4^4 (i.e. 3 should be subtracted) as they will be duplicates from lower number powers as in 2^4,2^6,2^8
This program is giving correct answer check here but I am unable to get the implemented logic,to be precise I am not getting how the duplicates are determined. Could somebody help ?
I may be missing something, but it seems to me this program gives the wrong answer. It's off by one. If I set MAX to 10, it's off by two.
I have read that some players like to produce approximate answers and then dictionary-attack the Project Euler servers to brute-force the problem. Other players consider that rather against the spirit of the thing.
Anyway—an algorithm like this (starting with N*M and eliminating duplicates) is the right way to tackle the problem, but as written this code doesn't make much sense to me. Note that in any case int(MAX*(log(i)/log(j))) is very sensitive to rounding error; but even if you eliminate that source of error by using integer arithmetic, the program still gives the wrong answer.
EDIT: How can we (correctly) count the duplicates?
First you must understand that two numbers are only the same if they have the same prime factorization. So there are only going to be duplicates a1b1 = a2b2 when a1 and a2 are distinct integer powers of the same integer, which I'll call x. For example,
97 = 314; this is possible because 9 and 3 are both powers of 3.
86 = 49; this is possible because 8 and 4 are both powers of 2.
So we have established that for all duplicates, a1 = xe1 and a2 = xe2 for some integers x, e1, and e1.
Then with a little algebra,
a1b1 = a2b2
xe1b1 = xe2b2
e1b1 = e2b2
Going back to the earlier examples,
97 = 314 because 2×7 = 1×14.
86 = 49 because 3×6 = 2×9.
So to find all duplicates for any given x, you only need to find duplicates for the simpler expression eb where 2 ≤ xe ≤ 100 and 2 ≤ b ≤ 100.
Here is a picture of that simpler problem, for x=3 and b ranging only from 2 to 10. I've marked two places where there are duplicates.
e=1 a=3 *********
e=2 a=9 * * * * * * * * *
e=3 a=27 * * * * * * * * *
e=4 a=81 * * * * * * * * *
| |
1*8 = 2*4 = 4*2 3*8 = 4*6
3^8 = 9^4 = 81^2 27^8 = 81^6
And here are the duplicates:
e=1 a=3 *********
e=2 a=9 x x x x * * * * *
e=3 a=27 x x x * x * * * *
e=4 a=81 x x x x x * * * *
The C++ program you found is trying to count them by visiting each pair of overlapping rows i and j, and calculating how much of row i overlaps row j. But again, unless I'm missing something, the program seems hopelessly imprecise. And it misses some pairs of rows entirely (you never have i=9 and j=27, or i=27 and j=81).
first, it sets res to 99*99 at line 6, because MAX was defined as 100. Then it enters a loop, with the condition that i is smaller than MAX. then it enters this pseudocode loop
int i;
int j;
int x=2;
for( j = i2; j <= MAX , j = ix)
{
res = res- (MAX* ( jlog(i) )+1;
x++;
}
sorry 'bout the not using <pre><code> above; but if I did I could not use <sup>
Please note log(a)/log(x) is the same as xlog(a)
comments on question because <sup> does not work there:
2log(2) = 1 because 21 = 2
2log(4) = 2 because 22 = 2
log(x) == 10log(x)
log(10) = 1
glog(x) = y => gy = x
Well, the question involves ways to combine two numbers chosen from a range. There are 99 possible numbers, so the number of combinations is 99 * 99, with possible duplicates. His basic algorithm here is to figure out how many duplicates are present, and subtract that value from the maximum.
As for counting duplicates, it might help intuitively to think of the numbers in terms of their prime factors. Raising a number to an integer power means multiplying it by itself; so, represented as a list of primes, this is equivalent to simply concatenating the lists. For instance, 6 is {2, 3}, so 6^3 would be {2, 2, 2, 3, 3, 3}. Note that if you count how many times each prime appears in the list, x^n will always have the same proportions as x, for instance 6^n will have an equal quantity of 2's and 3's. So, any two numbers in the range with the same proportion between primes must both be powers of some number.
So, in the full list, each distinct proportion of prime factors will appear repeatedly as x^2, x^3, x^4..., (x^3)^2, (x^3)^4..., (x^4)^2..., etc., where x is the smallest number with that proportion; more precisely, (x^m)^n where (x^m) <= 100 and 2 <= n <= 100. Since (x^m)^n is equal to x^(mn), counting duplicates amounts to counting the ways that x^(mn) can also be <= 100.
There are (at least) two ways to approach this problem. One is to start your count of distinct values at 0, and add one for each calculated value that hasn't been seen before. The other way is to calculate the maximum number of values, and then subtract one for each duplicate.
The poster is attempting the second methed. a can range from 2 to 100 for 99 values, as can b, so there are 99 * 99 produced values. The poster then attempts to subtract the duplicate values to get the correct answer.
Edit: However, the poster has written an incorrect algorithm.
For instance, setting MAX = 8 or 9. For 8 it should give 44 but it gives 45. For 9 it should give 54 but gives 56. Either they lucked out and happened across an algorithm that gives the correct answer for some inputs, or they reverse-engineered an algorithm that worked when MAX = 100 but not for all other values.