现在的位置: 首页 > 综合 > 正文

最小公约数(大整数乘除法,C++)

2019年03月03日 ⁄ 综合 ⁄ 共 4708字 ⁄ 字号 评论关闭
今天完善成的c++大整数乘法和除法,算了一个最小公约数。
是VIJOS-p1047,希望大家支持。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXLEN 200

//Convert input string into int

void StringToLargeInt(char *stra, char *strb, int *inta, int *intb, int *la, int *lb)
{
    //* means it can change in the function.
    //*name[mumber] means it's an array, and it can change in the function.
    
    *la = (int)strlen(stra);
    *lb = (int)strlen(strb);
    //how many numbers
    
    for(int i=0;i<*la;i++)
    {
        inta[i]=stra[*la-i-1]-'0';
    }
    for(int i=0;i<*lb;i++)
    {
        intb[i]=strb[*lb-i-1]-'0';
    }
    //turn the char to the int, and put the small one to the frount.
    //like turn "25436" to {6,3,4,5,2}.
}

//Compute the additon of two large int
//inta and intb are two inputs, and intc is the output
void LargeIntAdd(int *inta, int la, int *intb, int lb, int *intc,int *lc)
{
    int min, max, i;
    int *temp;
    
    memset(intc,0, *lc * sizeof(int));
    
    if(la>lb)
    {
        max = la;
        min = lb;
        temp = inta;
    }
    else
    {
        max = lb;
        min = lb;
        temp = intb;
    }
    
    for(i=0;i<min;i++)
    {
        intc[i] += inta[i] + intb[i];
        if(intc[i] >= 10)
        {
            intc[i+1]++;
            intc[i]-=10;
        }
    }
    while(i < max) {
        intc[i] += temp[i];
        if(intc[i] >= 10)
        {
            intc[i+1]++;
            intc[i]-=10;
        }
        i++;
    }
    
    if(intc[max] == 0)
        *lc = max ;
    else
        *lc = max + 1;
    
}

// Compare two large int
// -1 means a is less than b, 1 means a is larger than b
//0 means a is equal to b
int LargeIntCompare(int *inta, int la, int *intb, int lb)
{
    if(la > lb)
        return 1;
    else if (la < lb)
        return -1;
    else
    {
        for(int i = la-1;i >= 0;i--)
        {
            if(inta[i] > intb[i])
                return 1;
            else if (inta[i] < intb[i])
                return -1;
        }
        return 0;
    }
}
//Compute the substraction of two integers a - b
//inta stores the results of subtraction
void LargeIntSubtract(int *inta, int *la, int *intb, int lb)
{
    int i;
    
    for(i=0;i<*la;i++)
    {
        if(i<lb)
        {
            inta[i]=inta[i]-intb[i];
            if(inta[i]<0)
            {
                inta[i+1]--;
                inta[i]+=10;
            }
        }
        
        else
        {
            if(inta[i]<0)
            {
                inta[i+1]--;
                inta[i]+=10;
            }
        }
    }
    
    for(i = *la -1; i > 0 && inta[i] == 0; i--);
    
    *la= i + 1;
    
}

//add some zeros to the end of intb to make its length equal to la

int AllignLargeInt(int *intb, int la, int *lb)//a>b
{
    int x = la - *lb;
    
    if(x == 0)
        return 0;
    
    else
    {
        for(int i = la-1; i >= 0; i--)
        {
            if(i>=x)
                intb[i] = intb[i-x];
            else
                intb[i]=0;
        }
    }
    
    *lb=la;
    
    return x;
}

// remove zeros appending behind int b
// nZeros is number of zeros to be removed
int InvertAllignLargeInt(int *intb, int *lb, int nZeros)//a>b
{
    
    if(nZeros == 0)   return 0;
    
    for(int i = nZeros; i <= *lb - 1; i++)
        
        intb[i - nZeros] = intb[i];
    
    *lb -= nZeros;
    
    return 1;
}

//Compute the a / b = c ... d
// 123 / 60 = 2 ... 3

void LargeIntDevide(int *inta, int *la, int *intb, int *lb, int *intc, int *lc, int *intd,int *ld)
{
    int nAddZeros = AllignLargeInt(intb, *la, lb);
    int i,j;
    
    memset(intc,0,*lc *sizeof(int));
    memset(intd,0,*ld *sizeof(int));
    
    for(i = 0; i <= nAddZeros; i++)
    {
        j = 0;
        
        while(LargeIntCompare(inta, *la, intb + i, *lb - i) >= 0)
        {
            LargeIntSubtract(inta, la, intb + i, *lb - i);
            j++;
        }
        if (j > 0)
            intc[nAddZeros - i] = j;
    }
    
    for(i = nAddZeros; i > 0 && intc[i] == 0; i--);
    
    *lc = i + 1;
    
    for(i = *la - 1; i >= 0 && inta[i] == 0; i--);
    
    for(j = 0; j <= i ; j++)
        intd[j] = inta[j];
    
    *ld = i + 1;
    
}

// Compute the remaining of a % b, the result is stored in inta


void LargeIntMode(int *inta, int *la, int *intb, int *lb)
{
    int nAddZeros = AllignLargeInt(intb, *la, lb);
    int i;
    
    for(i = 0; i <= nAddZeros; i++)
    {
        while(LargeIntCompare(inta, *la, intb + i, *lb - i) >= 0)
            LargeIntSubtract(inta, la, intb + i, *lb - i);
    }
    
    
    for(i = *la - 1; i >= 0 && inta[i] == 0; i--);
    
    *la = i + 1;
    
    InvertAllignLargeInt(intb, lb, nAddZeros);
}

// return 0 means a == b is the divisor
// return 1 means b is the divisor

int LargeIntCommonDivisor(int *inta, int *la, int *intb, int *lb)
{
    
    int *largeInt, *smallInt;
    int *largeIntLen, *smallIntLen;
    int *tempInt, *tempIntLen;
    int res;
    
    res = LargeIntCompare(inta, *la, intb, *lb);
    if (res == 0) return 0;
    
    
    if (res > 0) {
        largeInt = inta;
        smallInt = intb;
        largeIntLen = la;
        smallIntLen = lb;
    }
    else
    {
        largeInt = intb;
        smallInt = inta;
        largeIntLen = lb;
        smallIntLen = la;
    }
    
    while (res != 0) {
        
        LargeIntMode(largeInt, largeIntLen, smallInt, smallIntLen);
        
        if (*largeIntLen == 0)  break;
        tempInt = largeInt;
        largeInt = smallInt;
        smallInt = tempInt;
        
        tempIntLen = largeIntLen;
        largeIntLen = smallIntLen;
        smallIntLen = tempIntLen;
        
        res  = LargeIntCompare(largeInt, *largeIntLen, smallInt, *smallIntLen);
    }
    
    for(int i = 0; i < *smallIntLen; i++)
        inta[i] = smallInt[i];
    
    *la = *smallIntLen;
    return 0;
}

void LargeIntMultiply(int *inta, int *la, int *intb, int *lb, int *intc, int *lc)
{
    int i,j,k;
    
    i = j = k = 0;
    memset(intc,0,sizeof(int) * (*lc + 1));
    
    for(i = 0; i < *la; i++)
        for(j = 0; j < *lb; j++)
        {
            intc[i+j] += inta[i] * intb[j];
        }
    
    for (k = 0; k < *la + *lb - 1; k++ )
        if(intc[k] >= 10) {
            intc[k+1] += intc[k] / 10;
            intc[k] = intc[k] % 10;
        }
    
    if (intc[k] != 0)
        *lc = k + 1;
    else
        *lc = k;
}

char* LargeIntPrint(int *inta, int la){
    
    char *temp = (char *)malloc(la +1);
    int i,j;
    
    for (i = la - 1,j = 0; i >= 0; i--,j++)
        sprintf(temp + j , "%1d",inta[i]);
    
    temp[j] = 0;
    
    return temp;
    
}


int main()
{
    char stra[MAXLEN+1];
    char strb[MAXLEN+1];
    
    int inta[MAXLEN+1];
    int intb[MAXLEN+1];
    int intc[MAXLEN+1];
    int intd[MAXLEN+1];
    int la = 0;
    int lb = 0;
    int lc = 0;
    int ld = 0;
    char *res;
    
    memset(stra,0,MAXLEN+1);
    memset(strb,0,MAXLEN+1);
    memset(inta,0,(MAXLEN+1) * sizeof(int));
    memset(intb,0,(MAXLEN+1) * sizeof(int));
    memset(intc,0,(MAXLEN+1) * sizeof(int));
    memset(intd,0,(MAXLEN+1) * sizeof(int));
    
    scanf("%s",stra);
    scanf("%s",strb);
    
    StringToLargeInt(stra, strb, inta, intb, &la, &lb);
    
    LargeIntMultiply(inta, &la, intb, &lb, intc, &lc);
    
    LargeIntCommonDivisor(inta, &la, intb, &lb);
    
    LargeIntDevide(intc, &lc, inta, &la, intd, &ld, intb, &lb);
    
    res = LargeIntPrint(intd, ld);
    
    printf("%s", res);
    
    free(res);
    
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.