大数除法
Sample Input
3 //表示接下来有三组测试数据
66666666666666666 //第一组输入
22222222222222222
33333333333333333 //第二组输入
3
55555555555555555 //第三组输入
555555
Sample Output
3
11111111111111111
100000100000
1
#include <iostream>
#include<string.h>
#include<stdio.h>
#define MAX_LEN 200
char szLine1[MAX_LEN + 10];
char szLine2[MAX_LEN + 10];
int an1[MAX_LEN + 10]; //被除数, an1[0]对应于个位
int an2[MAX_LEN + 10]; //除数, an2[0]对应于个位
int aResult[MAX_LEN + 10]; //存放商, aResult[0]对应于个位
/* Substract函数:长度为 nLen1的大整数 p1减去长度为 nLen2的大整数 p2
减的结果放在 p1里,返回值代表结果的长度
如不够减返回-1,正好减完返回 0
p1[0]、p2[0]是个位 */
int Substract( int * p1, int * p2, int nLen1, int nLen2)
{
int i;
if( nLen1 < nLen2 )
return -1;
//下面判断 p1是否比 p2大,如果不是,返回-1
bool bLarger = false;
if( nLen1 == nLen2 )
{
for( i = nLen1-1; i >= 0; i -- )
{
if( p1[i] > p2[i] )
bLarger = true;
else if( p1[i] < p2[i] )
{
if ( ! bLarger )
return -1;
}
}
}
for( i = 0; i < nLen1; i ++ ) //做减法
{
p1[i] -= p2[i]; //要求调用本函数时给的参数能确保当 i>=nLen2时,p2[i] = 0
if( p1[i] < 0 )
{
p1[i]+=10;
p1[i+1] --;
}
}
for( i = nLen1 -1 ; i >= 0 ; i-- )
if( p1[i] )
return i + 1;
return 0;
}
int main()
{
int t, n;
char szBlank[20];
scanf("%d", &n);
for( t = 0; t < n; t ++ )
{
scanf("%s", szLine1);
scanf("%s", szLine2);
int i, j;
int nLen1 = strlen( szLine1);
memset( an1, 0, sizeof(an1));
memset( an2, 0, sizeof(an2));
memset( aResult, 0, sizeof(aResult));
j=0;
for( i = nLen1 - 1; i >= 0 ; i --)
an1[j++] = szLine1[i] - '0';
int nLen2 = strlen(szLine2);
j=0;
for( i = nLen2 - 1; i >= 0 ; i --)
an2[j++] = szLine2[i] - '0';
if( nLen1 < nLen2 )
{
printf("0\n");
continue;
}
nLen1 = Substract( an1, an2, nLen1, nLen2) ;
if( nLen1 < 0)
{
printf("0\n");
continue;
}
else if( nLen1 == 0)
{
printf("1\n");
continue;
}
aResult[0] ++; //减掉一次了,商加 1
//减去一次后的结果长度是 nLen1
int nTimes = nLen1 - nLen2;
if( nTimes < 0) //减一次后就不能再减了
goto OutputResult;
else if( nTimes > 0 )
{
//将 an2 乘以 10的某次幂,使得结果长度和 an1相同
for( i = nLen1 -1; i >= 0; i -- )
{
if( i >= nTimes )
an2[i] = an2[i-nTimes];
else
an2[i] = 0;
}
}
nLen2 = nLen1;
for( j = 0 ; j <= nTimes; j ++ )
{
int nTmp;
//一直减到不够减为止
//先减去若干个 an2×(10 的 nTimes 次方),
//不够减了,再减去若干个 an2×(10 的 nTimes-1 次方),......
while( (nTmp = Substract(an1, an2+j, nLen1, nLen2-j)) >= 0)
{
nLen1 = nTmp;
aResult[nTimes-j]++; //每成功减一次,则将商的相应位加 1
}
}
OutputResult:
//下面的循环统一处理进位问题
for( i = 0; i < MAX_LEN; i ++ )
{
if( aResult[i] >= 10 )
{
aResult[i+1] += aResult[i] / 10;
aResult[i] %= 10;
}
}
//下面输出结果
bool bStartOutput = false;
for( i = MAX_LEN ; i >= 0; i -- )
if( bStartOutput)
printf("%d", aResult[i]);
else if( aResult[i] )
{
printf("%d", aResult[i]);
bStartOutput = true;
}
if(! bStartOutput )
printf("0\n");
printf("\n");
}
return 0;
}
2
#include <stdio.h>
#include <string.h>
#define MAX_LEN 110
int an1[MAX_LEN];
int an2[MAX_LEN];
int tmpAn2[MAX_LEN];
int anResult[MAX_LEN];
char szLine1[MAX_LEN];
char szLine2[MAX_LEN];
char szNouse[MAX_LEN];
int Substract( int nMaxLen, int * an1, int * an2)
//大整数an1减去an2。两者最多 nMaxLen 位,an1必须不小于an2, 差放在an1里
//返回差的最高非0位的位置
{ int nStartPos = 0;
for( int i = 0;i < nMaxLen ; i ++ ) {
an1[i] -= an2[i]; //逐位相减
if( an1[i] < 0 ) { //看是否要借位
an1[i] += 10;
an1[i+1] --; //借位
}
if( an1[i] )
nStartPos = i; //记录最高位的位置
}
return nStartPos;
}
int Length( int nMaxLen,int * an)
//求大整数的位数。0 算 0 位
{
int i;
for( i = nMaxLen -1 ; an[i] == 0 && i >= 0; i -- );
if( i >= 0 )
return i + 1;
return 0;
}
void ShiftLeft( int nMaxLen,int * an1, int * an2, int n)
//将大整数an1左移n位,即乘以10的n次方,结果放到an2里
{
memcpy( an2,an1,nMaxLen * sizeof(int));
if( n <= 0 )
return;
for( int i = nMaxLen -1 ; i >= 0; i -- )
if( i - n >= 0)
an2[i] = an1[i-n];
else
an2[i] = 0;
}
int * Max(int nMaxLen, int * an1, int * an2)
//求大整数an1和an2里面大的那个
//如果都是0,则返回NULL
{
bool bBothZero = true;
for( int i = nMaxLen -1; i >= 0 ; i -- ) {
if( an1[i] > an2[i] )
return an1;
else if( an1[i] < an2[i] )
return an2;
else if( an1[i] )
bBothZero = false;
}
if( bBothZero)
return NULL;
return an1;
}
int main()
{
int n;
scanf("%d",&n);
getchar();
while(n -- ) {
gets(szLine1);
gets(szLine2);
int i, j;
//库函数memeset将地址an1开始的sizeof(an1)字节内容置成0
//sizeof(an1)的值就是an1的长度
//memset函数在string.h中声明
memset( an1, 0, sizeof(an1));
memset( an2, 0, sizeof(an2));
//下面将szLine1中存储的字符串形式的整数转换到an1中去,
//an1[0]对应于个位
int nLen1 = strlen( szLine1);
for(j = 0, i = nLen1 - 1;i >= 0 ; i --)
an1[j++] = szLine1[i] - '0';
int nLen2 = strlen(szLine2);
for( j = 0, i = nLen2 - 1;i >= 0 ; i --)
an2[j++] = szLine2[i] - '0';
int nHighestPos = 0;
memset(anResult,0,sizeof(anResult));
int nShiftLen = Length(MAX_LEN,an1) - Length(MAX_LEN,an2);
//只要an1大于an2,就不停相减
while( Max(MAX_LEN,an1,an2) == an1 ) {
//算出an1的10的nShiftLen次方倍
ShiftLeft(MAX_LEN, an2, tmpAn2,nShiftLen);
//重复减去an1的10的nShiftLen次方倍,看能减几次
while( Max(MAX_LEN,an1,tmpAn2) == an1) {
Substract(MAX_LEN, an1,tmpAn2);
//记录商对应位
anResult[nShiftLen] ++;
}
//记录结果最高位的位置
if( nHighestPos == 0 && anResult[nShiftLen])
nHighestPos = nShiftLen;
nShiftLen --;
}
for( i = nHighestPos; i >= 0; i -- )
printf("%d", anResult[i]);
printf("\n");
}
return 0;
}
3
#include <stdio.h>
#include <string.h>
#define MAX_LEN 200
char szLine1[MAX_LEN + 10];
char szLine2[MAX_LEN + 10];
int an1[MAX_LEN + 10]; //被除数, an1[0]对应于个位
int an2[MAX_LEN + 10]; //除数, an2[0]对应于个位
int aResult[MAX_LEN + 10]; //存放商,aResult[0]对应于个位
/* Substract 函数:长度为 nLen1 的大整数p1 减去长度为nLen2 的大整数p2
减的结果放在 p1 里,返回值代表结果的长度
如不够减返回-1,正好减完返回 0
p1[0]、p2[0] 是个位 */
int Substract( int * p1, int * p2, int nLen1, int nLen2)
{
int i;
if( nLen1 < nLen2 )
return -1;
//下面判断p1 是否比p2 大,如果不是,返回-1
bool bLarger = false;
if( nLen1 == nLen2 )
{
for( i = nLen1-1; i >= 0; i -- )
{
if( p1[i] > p2[i] )
bLarger = true;
else if( p1[i] < p2[i] )
{
if ( ! bLarger )
return -1;
}
}
}
for( i = 0; i < nLen1; i ++ ) //做减法
{
p1[i] -= p2[i]; //要求调用本函数时给的参数能确保当i>=nLen2 时,p2[i] = 0
if( p1[i] < 0 )
{
p1[i]+=10;
p1[i+1] --;
}
}
for( i = nLen1 -1 ; i >= 0 ; i-- )
if( p1[i] )
return i + 1;
return 0;
}
int main()
{
int t, n;
char szBlank[20];
scanf("%d", &n);
for( t = 0; t < n; t ++ )
{
scanf("%s", szLine1);
scanf("%s", szLine2);
int i, j;
int nLen1 = strlen( szLine1);
memset( an1, 0, sizeof(an1));
memset( an2, 0, sizeof(an2));
memset( aResult, 0, sizeof(aResult));
j = 0;
for( i = nLen1 - 1; i >= 0 ; i --)
an1[j++] = szLine1[i] - '0';
int nLen2 = strlen(szLine2);
j = 0;
for( i = nLen2 - 1; i >= 0 ; i --)
an2[j++] = szLine2[i] - '0';
if( nLen1 < nLen2 )
{
printf("0\n");
continue;
}
nLen1 = Substract( an1, an2, nLen1, nLen2) ;
if( nLen1 < 0 )
{
printf("0\n");
continue;
}
else if( nLen1 == 0)
{
printf("1\n");
continue;
}
aResult[0] ++; //减掉一次了,商加1
//减去一次后的结果长度是 nLen1
int nTimes = nLen1 - nLen2;
if( nTimes < 0) //减一次后就不能再减了
goto OutputResult;
else if( nTimes > 0 )
{
//将 an2 乘以10 的某次幂,使得结果长度和 an1 相同
for( i = nLen1 -1; i >= 0; i -- )
{
if( i >= nTimes )
an2[i] = an2[i-nTimes];
else
an2[i] = 0;
}
}
nLen2 = nLen1;
for( j = 0 ; j <= nTimes; j ++ )
{
int nTmp;
//一直减到不够减为止
//先减去若干个 an2×(10 的 nTimes 次方),
//不够减了,再减去若干个 an2×(10 的 nTimes-1 次方),......
while( (nTmp = Substract(an1, an2+j, nLen1, nLen2-j)) >= 0)
{
nLen1 = nTmp;
aResult[nTimes-j]++; //每成功减一次,则将商的相应位加1
}
}
OutputResult:
//下面的循环统一处理进位问题
for( i = 0; i < MAX_LEN; i ++ )
{
if( aResult[i] >= 10 )
{
aResult[i+1] += aResult[i] / 10;
aResult[i] %= 10;
}
}
//下面输出结果
bool bStartOutput = false;
for( i = MAX_LEN ; i >= 0; i -- )
if( bStartOutput)
printf("%d", aResult[i]);
else if( aResult[i] )
{
printf("%d", aResult[i]);
bStartOutput = true;
}
if(! bStartOutput )
printf("0\n");
printf("\n");
}
return 0;
}