---
# System prepended metadata

title: Algorithm's Program 1

---

---
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)
