目录
- int的范围为[-,],为数量级;
- long long的范围为[],为数量级;
高精度加法
- 输入两个整数a,b,输出它们的和(a,b< )
- 输入两个整数a,b,输出它们的和(a,b< )
分析:
- 可以用long long类型和Int类型直接计算。
- 超int和long long的范围了,使用高精度进行求解。数组长度大于500
问题描述 :A + B =
图源:麦克老师讲算法
算法核心:
c[i] += a[i] +b[i] ; //注意 += 因为要加上进位。
c[i+1] =c[i] / 10; //进位。
c[i] =c[i] %10] //要舍去进位的那部分
将数值转置再计算。
1234+ 567 转过来 4321 +765 [0]位 4+7 , [1]位 3+6
P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream>
#include<iomanip>
#include<math.h>
#include<algorithm>
#include<string>
#include<cstring>
#include<stdio.h>
using namespace std;
int main()
{
//按字符数组输入,再存到数组里。
int a[505], b[505],c[505],la,lb,lc;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));//数组如果后续需要对本身进行运算,一定要记得初始化为0。
string s1, s2;
cin >> s1;
getchar();
cin >> s2;
la = s1.size();
lb = s2.size();
for (int i = 0; i < la; i++)
a[la - i-1 ] = s1[i] - '0'; //比如 1234 输入的时候 1是s1[0] 要把 1换为最高下标,4换为最小下标
for (int i = 0; i < lb; i++)
b[lb - i-1 ] = s2[i] - '0';
lc = max(la, lb) + 1;
for (int i = 0; i < lc; i++)
{
c[i] += a[i] + b[i];
c[i + 1] = c[i] / 10;
c[i] = c[i] % 10;
}
if (c[lc-1] == 0 && lc > 0) lc--;//删除前导0
for (int i = lc-1; i >= 0; i--)
printf("%d", c[i]); //从最高下标开始输出
return 0;
}
高精度减法
问题描述: A - B =
图源:麦克老师讲算法
算法核心:
- 如果a<b,交换a,b
- 如果a[i]<b[i],高位借一当十
if(a[i]<b[i])
{
a[i+1]--; //因为a[i]向a[i+1]借1,所以a[i+1]要减1
a[i]=a[i]+10;
}
c[i] = a[i] - b[i] ;
P2142 高精度减法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream>
#include<iomanip>
#include<math.h>
#include<algorithm>
#include<string>
#include<cstring>
#include<stdio.h>
using namespace std;
int main()
{
//按字符数组输入,再存到数组里。
int a[10100], b[10100],c[10100],la,lb,lc,i=0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));//数组一定要记得初始化为0。
string s1, s2;
cin >> s1;
cin >> s2;
if (s1 == s2)
cout << 0;
else
{
if (s1.size() < s2.size() || (s1.size() == s2.size() && s1[0] < s2[0]))
{
cout << "-";
swap(s1, s2);
}
la = s1.size();
lb = s2.size();
for (int i = 0; i < la; i++)
a[la - i - 1] = s1[i] - '0';
for (int i = 0; i < lb; i++)
b[lb - i - 1] = s2[i] - '0';
lc = max(la, lb);
for (int i = 0; i < lc; i++)
{
if (a[i] < b[i])
{
a[i + 1]--;//因为a[i]向a[i+1]借1,所以a[i+1]要减1
a[i] += 10;
}
c[i] = a[i] - b[i];
}
while (c[lc - 1] == 0) lc--;//删除前导0
for (int i = lc - 1; i >= 0; i--)
printf("%d", c[i]);
}
return 0;
}
高精度乘法
图源:麦克老师讲算法
算法核心:
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10; // 进位
c[i+j-1]%=10;
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
#include<iostream>
#include<iomanip>
#include<math.h>
#include<algorithm>
#include<string>
#include<cstring>
#include<stdio.h>
using namespace std;
int main()
{
//按字符数组输入,再存到数组里。
int a[105], b[105],c[10000],la,lb,lc;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));//数组一定要记得初始化为0。
string s1, s2;
cin >> s1;
cin >> s2;
if (s1 == "0"||s2 =="0")
cout << 0;
else
{
la = s1.size();
lb = s2.size();
for (int i = 0; i < la; i++)
a[la - i-1 ] = s1[i] - '0';
for (int i = 0; i < lb; i++)
b[lb - i-1 ] = s2[i] - '0';
for (int i = 0; i < la; i++)
{
for (int j = 0; j < lb; j++)
{
c[i + j ] += a[i] * b[j]; // 0+0-1小了!!! 不能i+j-1那样算。
c[i + j+1] += c[i + j ] / 10;
c[i + j ] %= 10;
}
}
lc = la + lb ;
while (c[lc] == 0&&lc>0) lc--;
for (int i = lc; i >= 0; i--)
printf("%d", c[i]);
}
return 0;
}
若以上代码i+j部分写为i+j-1,会报错
高精度除法
高精度除以低精度
图源:麦克老师讲算法
逐位试商法
算法核心:
c[i] = (x * 10 + a[i]) / b;
x = (x * 10 + a[i]) % b;
P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
char s[5005];
long long a[5005] = { 0 }, c[5005] = { 0 };
long long b, la, x = 0, lb = 0;
int main()
{
cin >> s >> b;
la = strlen(s);
for (int i = 0; i < la; i++) a[i] = s[i] - '0';
for (int i = 0; i < la; i++)
{
c[i] = (x * 10 + a[i]) / b;
x = (x * 10 + a[i]) % b;
}
while (c[lb] == 0 && lb < la-1) lb++; //删除前导0
for (int i = lb; i < la; i++) cout << c[i];
return 0;
}
高精度除以高精度
图源:麦克老师讲算法
算法核心:
减法模拟除法
信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
char s1[305], s2[305];
int a[305], b[305], c[305], tmp[305];//a为被除数 b为除数 c为商
//运算从1开始,0没有用到。[0]可以放数组位数。
void init(int *x)
{
char s[305];
cin >> s;
x[0] = strlen(s);
for (int i = 0; i < x[0]; i++)
{
x[x[0] - i] = s[i] - '0';
}
//要做减法,倒序存储字符数组。
}
int compare(int a[],int b[])
{
if(a[0] > b[0]) return 1;//比较a和b的位数。如果a的位数大于b的位数,那么a>b
if (a[0] < b[0]) return -1;
for (int i = a[0]; i > 0; i--)
{
if (a[i] > b[i]) return 1;
if (a[i] < b[i]) return -1;
}//若位数一样,比较最高位,最高位若一样,比较次一位。
return 0;
}
void jian(int a[], int b[])
{
for (int i = 1; i <= a[0]; i++)
{
if (a[i] < b[i])
{
a[i + 1]--;
a[i] = a[i] + 10;
}
a[i] = a[i] - b[i];
}
while (a[a[0]] == 0 && a[0] > 0) a[0]--;//删除前导0
}
void numcpy(int p[], int q[], int n)
{
for (int i = 1; i <= p[0]; i++) q[i + n - 1] = p[i];
q[0] = p[0] + n - 1;
}//已经转置了, 左移n位。将q整体移动n位放到q数组里。
void print(int a[])
{
if (a[0] == 0) { cout << 0; return; }
for (int i = a[0]; i > 0; i--) cout << a[i];
return;
}
int main()
{
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
init(a);//输入a
init(b);//输入b
memset(c, 0, sizeof(c));
c[0] = a[0] - b[0] + 1;//商的位数。
//如果被除数首位 > 除数的首位,则商的位数 = 被除数位数-除数的位数+1;
//如果被除数首位 < 除数的首位,则商的位数 = 被除数位数-除数的位数
//被除数首位 = 除数的首位, 要看两者的次位,以此类推。
for (int i = c[0]; i >= 1; i--)
{
memset(tmp, 0, sizeof(tmp));
numcpy(b, tmp, i);
while (compare(a, tmp) >= 0)
{
c[i]++;//减几次c[i]就是几。
jian(a, tmp);//减几次。
}
}
while (c[c[0]] == 0 && c[0] > 0) c[0]--;//去除前导0
print(c);//商
cout << endl;
print(a);//余数
return 0;
}