アルゴリズム設計と分析:第三章分治3.3バイナリ大整数の乗算
3509 ワード
/*
:
, n
x = 3141, A = 31 B=41
y = 5327, C = 53,D=27
x*y = AC*2^n + (AD + BC)*2^(n/2) + BD
= AC*2^n + ((A-B)*(D-C) + A*C + B*D)*2^n + BD //
:
:
3141 5327 10( )
9 11 2( )
:
16732107
99
731074749
*/
/*
, , x,y 10
*/
#include <stdio.h>
#include <iostream>
using namespace std;
bool g_valid;//
int sign(int a)// a
{
return a > 0 ? 1 : -1;
}
int myAbs(int a)
{
return a > 0 ? a : -1*a;
}
int digitCount(int a,int iBase)
{
int iTotalDigit = 0;
do
{
a /= iBase;//
iTotalDigit++;
}while(a);
return iTotalDigit;
}
int getBack(int a,int iBase,int iTotalDigit)//iBase
{
if(a <= 0)// a
{
g_valid = false;
return -1;
}
/* , 。 。1234: /2, ,
, 。
, , ,
*/
int iCnt = 0;
int iSum = 0;
int iFactor = 1;
do
{
iSum += iFactor*(a % iBase);
iFactor *= iBase;
a /= iBase;
iCnt++;
if(iCnt == iTotalDigit/2)
{
break;
}
}while(a);
return iSum;
}
// iBase^iExp
int myPow(int iBase,int iExp)
{
if(iExp == 1)//
{
return iBase;
}
int iRet = myPow(iBase,iExp/2);
iRet *= iRet;
if(iExp % 2 == 1)
{
iRet *= iBase;
}
return iRet;
}
int multiply(int x,int y,int iBase)
{
//
int iSign = sign(x) * sign(y);
x = myAbs(x);
y = myAbs(y);
//
int iTotalDigitX = digitCount(x,iBase);
int iTotalDigitY = digitCount(y,iBase);
//
if(iTotalDigitX != iTotalDigitY)
{
g_valid = false;
return -1;
}
// , 1,
if(x == 1 && y == 1)
{
return iSign;
}
else
{
//
int iDivideNum = myPow(iBase,iTotalDigitX/2);
int iBackX = getBack(x,iBase,iTotalDigitX);
// , 5341 5300, 100
int iFrontX = ( x - iBackX ) / iDivideNum;
int iBackY = getBack(y,iBase,iTotalDigitY);
int iFrontY = ( y - iBackY ) / iDivideNum;
//
int iM1 = iFrontX * iFrontY;
int iM2 = iBackX * iBackY;
int iM3 = (iFrontX - iBackX) * (iBackY - iFrontY) + iM1 + iM2;
int iRet = iSign * ( iM1*myPow(iBase,iTotalDigitX) + iM3*myPow(iBase,iTotalDigitX/2) + iM2 );
return iRet;
}
}
void process()
{
int x,y,iBase;
while(EOF != scanf("%d %d %d",&x,&y,&iBase))
{
g_valid = true;
int iRet = multiply(x,y,iBase);
if(g_valid)
{
printf("%d
",iRet);
}
else
{
printf(" %d %d , !
",x,y);
}
}
}
int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}