--- title: Algorithm's Program 1 description: 程式作業 --- # Group 2 組員: 王承隆、賴文宏、施宗佑、王昱翔、王柏喬、莊淳方、傅文宗 # 1. ## Time complexity: $O(n^2)$ n = half length of $x$ $x = a*10^n + b$ $y = c*10^n + d$ $x*y = (a*10^n + b) * (c*10^n + d)$ $= a*c*10^{2n} + (a*d + b*c)*10^{n} + b*d$ using only int and string ## pseudocode && analysis ``` Psuedocode mul(num1, num2) //num1 and num2 are strings of integer //the addition, subtract and multiplication are procedures //taking two strings of integer and returning a string if num1*num2 doen't overflow return num1*num2 if num1[0] == '-' return -karatsuba(-num1, num2) if num2[0] == '-' return -karatsuba(num1, -num2) if num1.length() < 2 or num2.length() < 2 return num1 * num2 n = num1.length() splitPosition = n / 2 high1 = num1[0:splitPosition-1] low1 = num1[splitPosition:n-1] high2 = num2[0:splitPosition-1] low2 = num2[splitPosition: n-1] z0 = karatsuba(low1, low2) z1 = karatsuba(low1, high2) z2 = karatsuba(high1, low2) z3 = karatsuba(high1, high2) return z3 * 10 ^ (2 * splitPosition) + (z1 + z2) * 10 ^ (splitPosition) + z0 ``` 4 multiplication of 2 integers of length n/2 give $4 T(n/2)$ 4 additions give $O(n)$ $T(n) = 4T(n/2)+O(n)=O(n^{2}).$(by Master theorem) ## code ```C++= #include <iostream> #include <string> #include <ctime> #define max(a,b) ((a) > (b) ? (a) : (b)) using namespace std; string add(string lhs, string rhs); string subtract(string lhs, string rhs); string add(string lhs, string rhs) { bool lne = false, rne = false; if (lhs[0]=='-') lne = true; if (rhs[0]=='-') rne = true; if(lne&&rne) return '-'+add(lhs.substr(1,lhs.length()-1), rhs.substr(1,rhs.length()-1)); else if(lne&&!rne) return subtract(rhs, lhs.substr(1,lhs.length()-1)); else if(!lne&&rne) return subtract(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); int carry = 0; int sum_col; string result; while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); for (int i = length-1; i >= 0; i--) { sum_col = (lhs[i]-'0') + (rhs[i]-'0') + carry; carry = sum_col/10; result.insert(0,to_string(sum_col % 10)); } if (carry) result.insert(0,to_string(carry)); return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } string subtract(string lhs, string rhs) { bool lne = false, rne = false; if (lhs[0]=='-') lne = true; if (rhs[0]=='-') rne = true; if(lne&&rne) return subtract(rhs.substr(1,rhs.length()-1), lhs.substr(1,lhs.length()-1)); else if(lne&&!rne) return subtract(rhs, lhs.substr(1,lhs.length()-1)); else if(!lne&&rne) return add(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); int diff; string result; while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); for (int i = length-1; i >= 0; i--) { diff = (lhs[i]-'0') - (rhs[i]-'0'); if (diff >= 0) result.insert(0, to_string(diff)); else { // borrow from the previous column int j = i - 1; while (j >= 0) { lhs[j] = ((lhs[j]-'0') - 1) % 10 + '0'; if (lhs[j] != '9') break; else j--; } result.insert(0, to_string(diff+10)); } } return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } string multiply(string lhs, string rhs) { if (lhs[0] == '-') return '-'+multiply(lhs.substr(1,lhs.length()-1), rhs); if (rhs[0] == '-') return '-'+multiply(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); if (length == 1) return to_string((lhs[0]-'0')*(rhs[0]-'0')); string lhs0 = lhs.substr(0,length/2); string lhs1 = lhs.substr(length/2,length-length/2); string rhs0 = rhs.substr(0,length/2); string rhs1 = rhs.substr(length/2,length-length/2); string p0 = multiply(lhs0,rhs0); string p1 = multiply(lhs1,rhs1); string p2 = multiply(lhs0, rhs1); string p3 = multiply(lhs1, rhs0); for (int i = 0; i < 2*(length-length/2); i++) p0.append("0"); for (int i = 0; i < length-length/2; i++) p2.append("0"); for (int i = 0; i < length-length/2; i++) p3.append("0"); string result = add(add(add(p0,p1),p2), p3); return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } int main() { string s1, s2; cin >> s1 >> s2; clock_t a,b; a=clock(); cout << multiply(s1,s2) << endl; b=clock(); cout<<double(b-a)/1000; return 0; } ``` ## graph ![](https://i.imgur.com/ytSSTdC.png) # 2. ## Time complexity: $O(n^{lg3})$ by Karatsuba algorithm n = half length of $x$ $x = a*10^n + b$ $y = c*10^n + d$ $x*y = (a*10^n + b) * (c*10^n + d)$ $= a*c*10^{2n} + (a*d + b*c)*10^{n} + b*d$ $= a*c*10^{2n} + ((a+b)*(c+d)-a*b - b*d)*10^{n} + b*d$ using only int and string ## pseudocode && analysis ```pseudocode= karatsuba(num1, num2) //num1 and num2 are strings of integer //the addition, subtract and multiplication are procedures //taking two strings of integer and returning a string if num1*num2 doen't overflow return num1*num2 if num1[0] == '-' return -karatsuba(-num1, num2) if num2[0] == '-' return -karatsuba(num1, -num2) if num1.length() < 2 or num2.length() < 2 return num1 * num2 n = num1.length() splitPosition = n / 2 high1 = num1[0:splitPosition-1] low1 = num1[splitPosition:n-1] high2 = num2[0:splitPosition-1] low2 = num2[splitPosition: n-1] z0 = karatsuba(low1, low2) z1 = karatsuba(low1+high1, low2+high2) z2 = karatsuba(high1, high2) return z2 * 10 ^ (2 * splitPosition) + (z1 - z2 - z0) * 10 ^ (splitPosition) + z0 ``` 3 multiplication of 2 integers of length n/2 give $3T(n/2)$ 4 additions,and 2 subtractions of integers of at most 2n bits give $O(n)$ $T(n) = 3T(n/2)+O(n)=O(n^{log3}).$(by Master theorem) ## code ```C++= #include <iostream> #include <string> #include <ctime> #define max(a,b) ((a) > (b) ? (a) : (b)) using namespace std; string add(string lhs, string rhs); string subtract(string lhs, string rhs); string add(string lhs, string rhs) { bool lne = false, rne = false; if (lhs[0]=='-') lne = true; if (rhs[0]=='-') rne = true; if(lne&&rne) return '-'+add(lhs.substr(1,lhs.length()-1), rhs.substr(1,rhs.length()-1)); else if(lne&&!rne) return subtract(rhs, lhs.substr(1,lhs.length()-1)); else if(!lne&&rne) return subtract(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); int carry = 0; int sum_col; string result; while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); for (int i = length-1; i >= 0; i--) { sum_col = (lhs[i]-'0') + (rhs[i]-'0') + carry; carry = sum_col/10; result.insert(0,to_string(sum_col % 10)); } if (carry) result.insert(0,to_string(carry)); return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } string subtract(string lhs, string rhs) { bool lne = false, rne = false; if (lhs[0]=='-') lne = true; if (rhs[0]=='-') rne = true; if(lne&&rne) return subtract(rhs.substr(1,rhs.length()-1), lhs.substr(1,lhs.length()-1)); else if(lne&&!rne) return subtract(rhs, lhs.substr(1,lhs.length()-1)); else if(!lne&&rne) return add(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); int diff; string result; while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); for (int i = length-1; i >= 0; i--) { diff = (lhs[i]-'0') - (rhs[i]-'0'); if (diff >= 0) result.insert(0, to_string(diff)); else { // borrow from the previous column int j = i - 1; while (j >= 0) { lhs[j] = ((lhs[j]-'0') - 1) % 10 + '0'; if (lhs[j] != '9') break; else j--; } result.insert(0, to_string(diff+10)); } } return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } string multiply(string lhs, string rhs) { if (lhs[0] == '-') return '-'+multiply(lhs.substr(1,lhs.length()-1), rhs); if (rhs[0] == '-') return '-'+multiply(lhs, rhs.substr(1,rhs.length()-1)); int length = max(lhs.size(), rhs.size()); while (lhs.size() < length) lhs.insert(0,"0"); while (rhs.size() < length) rhs.insert(0,"0"); if (length == 1) return to_string((lhs[0]-'0')*(rhs[0]-'0')); string lhs0 = lhs.substr(0,length/2); string lhs1 = lhs.substr(length/2,length-length/2); string rhs0 = rhs.substr(0,length/2); string rhs1 = rhs.substr(length/2,length-length/2); string p0 = multiply(lhs0,rhs0); string p1 = multiply(lhs1,rhs1); string p2 = multiply(add(lhs0,lhs1),add(rhs0,rhs1)); string p3 = subtract(p2,add(p0,p1)); for (int i = 0; i < 2*(length-length/2); i++) p0.append("0"); for (int i = 0; i < length-length/2; i++) p3.append("0"); string result = add(add(p0,p1),p3); return result.erase(0, min(result.find_first_not_of('0'), result.size()-1)); } int main() { string s1, s2; cin >> s1 >> s2; clock_t a,b; a=clock(); cout << multiply(s1,s2) << endl; b=clock(); cout<<double(b-a)/1000; return 0; } ``` ## graph ![](https://i.imgur.com/MgprbdL.png)