I am in the midst of solving a simple combination problem whose solution is 2^(n-1).
The only problem is 1 <= n <= 2^31 -1 (max value for signed 32 bit integer)
I tried using Java's BigInteger class but It times out for numbers 2^31/10^4 and greater, so that clearly doesn't work out.
Furthermore, I am limited to using only built-in classes for Java or C++.
Knowing I require speed, I chose to build a class in C++ which does arithmetic on strings.
Now, when I do multiplication, my program multiplies similarly to how we multiply on paper for efficiency (as opposed to repeatedly adding the strings).
But even with that in place, I can't multiply 2 by itself 2^31 - 1 times, it is just not efficient enough.
So I started reading texts on the problem and I came to the solution of...
2^n = 2^(n/2) * 2^(n/2) * 2^(n%2)
(where / denotes integer division and % denotes modulus)
This means I can solve exponentiation in a logarithmic number of multiplications. But to me, I can't get around how to apply this method to my code? How do I choose a lower bound and what is the most efficient way to keep track of the various numbers that I need for my final multiplication?
If anyone has any knowledge on how to solve this problem, please elaborate (example code is appreciated).
UPDATE
Thanks to everyone for all your help! Clearly this problem is meant to be solved in a realistic way, but I did manage to outperform java.math.BigInteger
with a power function that only performs ceil(log2(n)) iterations.
If anyone is interested in the code I've produced, here it is...
using namespace std;
bool m_greater_or_equal (string & a, string & b){ //is a greater than or equal to b?
if (a.length()!=b.length()){
return a.length()>b.length();
}
for (int i = 0;i<a.length();i++){
if (a[i]!=b[i]){
return a[i]>b[i];
}
}
return true;
}
string add (string& a, string& b){
if (!m_greater_or_equal(a,b)) return add(b,a);
string x = string(a.rbegin(),a.rend());
string y = string(b.rbegin(),b.rend());
string result = "";
for (int i = 0;i<x.length()-y.length()+1;i++){
y.push_back('0');
}
int carry = 0;
for (int i =0;i<x.length();i++){
char c = x[i]+y[i]+carry-'0'-'0';
carry = c/10;
c%=10;
result.push_back(c+'0');
}
if (carry==1) result.push_back('1');
return string(result.rbegin(),result.rend());
}
string multiply (string&a, string&b){
string row = b, tmp;
string result = "0";
for (int i = a.length()-1;i>=0;i--){
for (int j= 0;j<(a[i]-'0');j++){
tmp = add(result,row);
result = tmp;
}
row.push_back('0');
}
return result;
}
int counter = 0;
string m_pow (string&a, int exp){
counter++;
if(exp==1){
return a;
}
if (exp==0){
return "1";
}
string p = m_pow(a,exp/2);
string res;
if (exp%2==0){
res = "1"; //a^exp%2 is a^0 = 1
} else {
res = a; //a^exp%2 is a^1 = a
}
string x = multiply(p,p);
return multiply(x,res);
//return multiply(multiply(p,p),res); Doesn't work because multiply(p,p) is not const
}
int main(){
string x ="2";
cout<<m_pow(x,5000)<<endl<<endl;
cout<<counter<<endl;
return 0;
}