第二部分 基础算法 --> 第一章 高精度计算
高精度算法
1168:大整数加法
【题目描述】
求两个不超过200位的非负整数的和。
【输入】
有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。
【输出】
一行,即相加后的结果。
结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
【输入样例】
22222222222222222222
33333333333333333333
【输出样例】
55555555555555555555
【参考程序】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
//初始化
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
//高精加
string add(string a, string b){
init(a, b);
lc=max(la, lb);
for(int i=0; i<lc; i++){
C[i]=A[i]+B[i]+C[i];
if(C[i]>9){
C[i+1]=C[i]/10, C[i]%=10;
}
}
while(C[lc]) lc++;
string c;
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
//去除多余前导0
string rem(string a){
char s[1001];
int len=a.length(), p=0;
for(int i=0; i<len; i++){
if(a[i]=='0' && p==0) continue;
else s[p++]=a[i];
}
if(p==0) s[p++]='0';
s[p]='\0';
string b=""; b.append(s);
return b;
}
int main() {
string a,b; cin>>a>>b;
a=rem(a), b=rem(b);
cout<<add(a, b)<<endl;
return 0;
}
1169:大整数减法
【题目描述】
求两个大的正整数相减的差。
【输入】
共2行,第1行是被减数a,第2行是减数b(a > b)。
每个大整数不超过200位,不会有多余的前导零。
【输出】
一行,即所求的差。
【输入样例】
9999999999999999999999999999999999999
9999999999999
【输出样例】
9999999999999999999999990000000000000
【参考程序】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
//初始化
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
//高精减
string sub(string a, string b){
init(a, b);
lc=max(la, lb);
for(int i=0; i<lc; i++){
C[i] = A[i]-B[i];
if(C[i]<0) A[i+1]--, C[i]+=10;
}
while(lc>1 && C[lc-1]==0) lc--;//去除前导 0
string c;
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
int main() {
string a,b; cin>>a>>b;
if(a<b){
swap(a, b); cout<<"-";
}
cout<<sub(a, b)<<endl;
return 0;
}
1174:大整数乘法
【题目描述】
求两个不超过200位的非负整数的积。
【输入】
有两行,每行是一个不超过200位的非负整数,没有多余的前导0。
【输出】
一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。
【输入样例】
12345678900
98765432100
【输出样例】
1219326311126352690000
【参考程序】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
string mul(string a, string b){
init(a, b);
lc=la+lb-1;
for(int i=0; i<la; i++){
for(int j=0; j<lb; j++){
C[i+j] += A[i]*B[j];
}
}
for(int i=0; i<lc; i++){
if(C[i]>9){
C[i+1] += C[i]/10, C[i]%=10;
}
}
while(C[lc]) lc++;
string c;
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
int main() {
string a,b;
while(cin>>a>>b){
cout<<mul(a, b)<<endl;
}
return 0;
}
1307:【例1.3】高精度乘法
【题目描述】
输入两个高精度正整数M和N(M和N均小于100位)。
求这两个高精度数的积。
【输入】
输入两个高精度正整数M和N。
【输出】
求这两个高精度数的积。
【输入样例】
36
3
【输出样例】
108
【参考程序】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
//初始化
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
//高精乘
string mul(string a, string b){
init(a, b);
lc=la+lb-1;
for(int i=0; i<la; i++){
for(int j=0; j<lb; j++){
C[i+j] += A[i]*B[j];
}
}
for(int i=0; i<lc; i++){
if(C[i]>9){
C[i+1] += C[i]/10, C[i]%=10;
}
}
while(C[lc]) lc++;
while(lc>1&&C[lc-1]==0) lc--;//去除前导 0, 10*0=0
string c="";
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
int main() {
string a, b; cin>>a>>b;
cout<<mul(a, b)<<endl;
return 0;
}
1170:计算2的N次方
【题目描述】
任意给定一个正整数N(N<=100),计算2的n次方的值。
【输入】
输入一个正整数N。
【输出】
输出2的N次方的值。
【输入样例】
5
【输出样例】
32
【参考程序1】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
string mul(string a, string b){
init(a, b);
lc=la+lb-1;
for(int i=0; i<la; i++){
for(int j=0; j<lb; j++){
C[i+j] += A[i]*B[j];
}
}
for(int i=0; i<lc; i++){
if(C[i]>9){
C[i+1] += C[i]/10, C[i]%=10;
}
}
while(C[lc]) lc++;
string c;
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
int main() {
int n; cin>>n;
string a="1",b="2";
for(int i=1; i<=n; i++){
a = mul(a, b);
}
cout<<a<<endl;
return 0;
}
1172:求10000以内n的阶乘
【题目描述】
求10000以内n的阶乘。
【输入】
只有一行输入,整数n(0≤n≤10000)。
【输出】
一行,即n!的值。
【输入样例】
4
【输出样例】
24
此题数据较严格,如果单纯如下参考程序1,会被卡时间
1e3*(3e4)^2 > 1e9 游戏结束
【参考程序1】
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6;
int A[N], B[N], C[N], la, lb, lc;
//初始化
void init(string a, string b){
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
memset(C, 0, sizeof(C));
la=a.length(), lb=b.length();
for(int i=0; i<la; i++) A[i]=a[i]-'0';
for(int i=0; i<lb; i++) B[i]=b[i]-'0';
reverse(A, A+la), reverse(B, B+lb);
}
//高精乘
string mul(string a, string b){
init(a, b);
lc=la+lb-1;
for(int i=0; i<la; i++){
for(int j=0; j<lb; j++){
C[i+j] += A[i]*B[j];
}
}
for(int i=0; i<lc; i++){
if(C[i]>9){
C[i+1] += C[i]/10, C[i]%=10;
}
}
while(C[lc]) lc++;
while(lc>1&&C[lc-1]==0) lc--;//去除前导 0, 10*0=0
string c="";
for(int i=lc-1; i>=0; i--) c.append(1, C[i]+'0');
return c;
}
//整数转string
string tos(int n){
char s[1001];
int cnt=0;
while(n){
s[cnt++]=n%10+'0';
n/=10;
}
s[cnt]='\0';
reverse(s, s+cnt);
string a=""; a.append(s);
return a;
}
int main() {
int n; cin>>n;
string a="1";
for(int i=1; i<=n; i++){
a = mul(a, tos(i));
}
cout<<a<<endl;
return 0;
}
【参考程序2】
#include<bits/stdc++.h>
using namespace std;
const int N =1e6;
int a[N]={0, 1};
int main(){
int n, l=1; scanf("%d", &n);
for(int i=1; i<=n; i++){
for(int j=1; j<=l; j++){
a[j] = a[j]*i;
a[j] += a[j-1]/10;
a[j-1] %= 10;
if(a[j]>9 && j==l) l++;
}
}
for(int i=l; i>=1; i--) printf("%d", a[i]);
return 0;
}
1175:除以13
【题目描述】
输入一个大于0的大整数N,长度不超过100位,要求输出其除以13得到的商和余数。
【输入】
一个大于0的大整数,长度不超过100位。
【输出】
两行,分别为整数除法得到的商和余数。
【输入样例】
2132104848488485
【输出样例】
164008065268345
0
【参考程序】
1308:【例1.5】高精除
【题目描述】
高精除以高精,求它们的商和余数。
【输入】
输入两个低于300位的正整数。
【输出】
输出商和余数。
【输入样例】
1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867
【输出样例】
999999999748590
179780909068307566598992807564736854549985603543237528310337
【参考程序】

浙公网安备 33010602011771号