又是不知道多少天地学习,真是忙忙碌碌,忙忙碌碌!最近很多人问到我一个求阶乘之和的题,本来俩个for循环搞定的事,确实不难,然而阶乘的范围有点大,大到什么程度呢?大到了一个long long 都装不下!这里就要引入我们的算法高精度了。
要解决这道题我们首先需要学会高精乘法,和高精加法。
直接上代码:
A+B问题:
第一步:将俩个long long存不下的数用俩个字符串a,b吸入,接着我们还需要俩个数组,用l,和r,来表示。
string a, b;//俩个数
int l[505],r[505],s[505];
第二步:将a和b中的数用逆序(方便后面做处理,从个位开始加),转化到数组l和r中去
for (int i = 0; i < la; i++) {
l[i] = a[la - i-1] - '0';
//转化
}
for (int i = 0; i < lb; i++) {
r[i] = b[lb - i - 1] - '0';
}
第三步:进行加法运算,(细节都在带码中了)
ma = max(la, lb) ;//确定上线,选取最大的那个
for (int i = 0; i < ma; i++) {
s[i] += (l[i] + r[i]);//注意是加等于
s[i + 1] = s[i] / 10;//关键:如果大于9就说明需要进位了,这也是上一部需要+=的原因
s[i] = s[i] % 10;//将个位保留
}
最后:输出,注意因为输出是从末尾输出的,所以输出的边界很重要,一定要除去前导0
while (s[ma] == 0&&ma>0)ma--;//去除前导0;
for (int i = ma; i > -1; i--) {
cout << s[i];
}
A*B问题
前面的处理方法和加法都差不多,我就不做过多的叙说,这里主要讲一下计算的步骤和输出需要注意的地方
for (int i = 1; i <=la; i++) {//双重循环,每一位都要相乘
for (int j = 1; j <= lb; j++) {//每一位乘完再加
c[i + j - 1] += m[i] * n[j];//注意+=,理解一下他的意思
c[i + j] += c[i + j - 1] / 10;//注意+=
c[i + j - 1] %= 10;
}
}
主体都能理解,但这里最需要理解的是一个数的第i位乘第j位就会变成i+j-1位,
最后就是输出了
//去除前导0
int q = la + lb;
while (c[q] == 0 && q > 1)q--;
//输出
for (int i = q; q > 0; q--) {
cout << c[q];
}
阶乘的和
终于来到了大boss
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1e4;
int a[N], b[N];
int main() {
int n;
cin >> n;
a[1] = 1; b[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j<=100; j++) {
a[j] *= i;//a[j]相当于i的阶乘
}
//转化
for (int j = 1; j <=100; j++) {
if (a[j] > 9) {
int p = a[j] / 10;
a[j + 1] += p;
a[j] %= 10;
}
}//相加
for (int j = 1; j <= 100; j++) {
b[j] += a[j];
if (b[j] > 9) {
int p = b[j] / 10;
b[j + 1] += p;
b[j] %= 10;
}
}
}
//输出
int m= 2 * n;
while (b[m] == 0 && m > 1)m--;//去除前导0
for (int i = m; i > 0; i--) {
printf("%d", b[i]);
}
return 0;
}
这里再附加一道高精度减法,大家可以去思考一下再来看看我的代码:
答案代码奉上:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string a, b;
int r[20000], l[20000],c[20000];
int main() {
cin >> a >> b;
int m;
int mark;
int la = a.length(); int lb = b.length();
if (la >lb||(la==lb&&a>b)||a==b) {//string类型可以直接比大小,但只有等长的时候。才会准确
mark=0;
m = la;
}
else {
mark = 1;
m = lb;
}//比较俩个数的大小
for (int i = 0; i < la; i++) {//判断是否需要加-号,重点
l[i] = a[la - i - 1] - '0';
}
for (int i = 0; i < lb; i++) {
r[i] = b[lb - i - 1]-'0';
}
if (!mark) {
for (int i = 0; i < m; i++) {
if (l[i] >= r[i]) {
c[i] = l[i] - r[i];
}
else {
c[i] = l[i] + 10 - r[i];//借位
l[i + 1] -= 1;
}
}
}
else {
for (int i = 0; i < m; i++) {
if (r[i] >= l[i]) {
c[i] = r[i] - l[i];
}
else {
c[i] = r[i] + 10 - l[i];
r[i + 1] -= 1;
}
}
}
m = m - 1;
while (c[m] == 0&&m>0)m--;//处理前导0;
if(!mark){
for (int i = m; i > -1; i--) {
cout << c[i];
}
}
else {
putchar('-');
for (int i = m; i > -1; i--) {
cout << c[i];
}
}
return 0;
}