#include <iostream>
using namespace std;
int main() {
private static String pad ( final String x, final int n)
{
String res = new String(x);
for (int i=1; i<=n; i++)
{
res = "0"+res;
};
return res;
} /** of pad */
/**
* Remove leading '0's from string x
*/
private static String trim_down ( final String x )
{
String res = new String(x);
while (res.startsWith("0"))
{
res = res.substring(1);
};
return res;
} /** of trim_down */
/**
* Shift (i.e. Multiply by 10^n)
*/
public static String shift_n (final String x, final int n)
{
String res = new String(x);
for (int i=1; i<=n; i++)
{
res=res+"0";
};
return res;
} /** of shift_n */
/**
* Subtraction x-y where x >= y assumed
*/
public static String monus(final String x, final String y)
{
char[] tx = new String(x).toCharArray(); /** Process x as char array. */
char[] ty = new String(y).toCharArray(); /** Process y as char array. */
String res = new String(""); /** Eventual result. */
char borrow = '0'; /** Borrow digit. */
int i; /** Loop counter. */
/**
* Pad tx/ty to same length if necessary.
*/
if ( !(tx.length==ty.length) )
{
int diff = tx.length-ty.length;
if (diff<0)
{
tx = pad(x,-diff).toCharArray();
}
else
{
ty = pad(y,diff).toCharArray();
};
};
/**
* Main subtraction calculation (N.B. tx[0] is most sig. digit, hence
* loop iterate for tx.length-1 to 0)
*/
for (i=tx.length-1; i>=0; i=i-1)
{
int bx = (int)tx[i] - (int)borrow; /** Convert tx[i] remembering borrow. */
int by = (int)ty[i]-(int)'0'; /** Convert ty[i]. */
int tv = bx-by; /** Result digit */
/**
* Update borrow and correct tv if needed.
*/
if (tv<0)
{
borrow='1'; tv=tv+10;
}
else
{
borrow='0';
};
res=(char) ( tv+(int)'0')+res; /** Pack digit into result string. */
};
return res;
} /** of monus */
/**
* Addition.
* Much the same as monus method (but with carry instead of borrow).
*/
public static String add(final String x, final String y)
{
char[] tx = new String(x).toCharArray();
char[] ty = new String(y).toCharArray();
String res = new String("");
char carry = '0';
int i;
if ( !(tx.length==ty.length) )
{
int diff = tx.length-ty.length;
if (diff<0)
{
tx = pad(x,-diff).toCharArray();
}
else
{
ty = pad(y,diff).toCharArray();
};
};
for (i=tx.length-1; i>=0; i=i-1)
{
int tv = (int)tx[i]-(int)'0' +(int)ty[i]-(int)'0' +(int)carry - (int)'0';
if (tv>9)
{
carry='1'; tv=tv-10;
}
else
{
carry='0';
};
res=(char) ( tv+(int)'0')+res;
};
if (carry=='1')
{
res = "1"+res;
};
return res;
}
/**
* Multiplication using Karatsuba Method
*/
public static String multiply ( final String x, final String y)
{
char[] tx = new String(x).toCharArray();
char[] ty = new String(y).toCharArray();
int n; /** Number of digits in (even length) tx. */
String res = new String();
/**
* Equalise Lengths before computation
*/
if ( !(tx.length==ty.length) )
{
int diff = tx.length-ty.length;
if (diff<0)
{
tx = pad(x,diff).toCharArray();
}
else
{
ty = pad(y,diff).toCharArray();
};
};
/**
* Recursive Base (4 or fewer digits)
*/
int mx = Math.max(tx.length, ty.length);
if (mx <= 4)
{
res = String.valueOf ( new BigInteger(new String(tx)).multiply(new BigInteger(new String(ty))));
return res;
}
else /** Number of digits > 4 so recurse. */
{
if (tx.length%2==1)
{
tx= pad(String.valueOf(tx),1).toCharArray(); /** Add leading 0 if odd length; */
ty= pad(String.valueOf(ty),1).toCharArray();
};
n = tx.length;
/**
* DIVIDE STAGE:
*
* Form appropriate substrings: tx, tx are n digit
* equivalents of x,y where n is even.
*
* a = (n/2) Most significant digits x
* b= (n/2) Least significant digits x
* c = (n/2) Most significant digits y
* d= (n/2) Least significant digits y
*/
String a = new String( (String.valueOf(tx)).substring(0,n/2) );
String b = new String( (String.valueOf(tx)).substring(n/2,n) );
String c = new String( (String.valueOf(ty)).substring(0,n/2) );
String d = new String( (String.valueOf(ty)).substring(n/2,n) );
/**
* Now form the representations for a+b, c+d (arithmetic addition)
*/
String a_plus_b = new String ( add(a,b) );
String c_plus_d = new String ( add(c,d) );
/**
* CONQUER STAGE
*
* Recursive Invocations:
* u=a*c; v=b*d; w=(a+b)*(c+d)
*/
String u = new String (multiply(a,c));
String v = new String (multiply(b,d));
String w = new String (multiply(a_plus_b,c_plus_d));
/**
* COMBINE STAGE
*
* Compute: u*10^n + (w-(u+v))*10^(n/2) + v
* = (a*10^(n/2)+b)*(c*10^(n/2)+d)
* = x*y
*
* s*10^k performed by shift_n(s,k);
* Result is stripped of superfluous leading '0's
*/
String u_plus_v = new String ( add(u,v) );
String w_monus_uv = new String ( monus(w,u_plus_v) );
String res1 = new String ( shift_n(u,n) );
String res2 = new String ( add(res1,shift_n(w_monus_uv,n/2)) );
String res3 = new String ( add(res2,v) );
return trim_down(res3);
}
}
return 0;
}