信息学奥赛一本通--基础算法--高精度算法

信息学奥赛一本通基础篇中的高精度算法。 

目录

1.高精度乘法

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

 2.高精度除法

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

3.大整数加法

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

4.大整数减法

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

5.计算2的N次方

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

6.大整数的因子

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

 7.求10000以内n的阶乘

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

8.阶乘和

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

9.大整数乘法

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】

 10.除以13

【题目描述】

【输入】

【输出】

【输入样例】

【输出样例】


 

1.高精度乘法

【题目描述】

输入两个高精度正整数M和N(M和N均小于100位)。求这两个高精度数的积。

【输入】

输入两个高精度正整数M和N。

【输出】

求这两个高精度数的积。

【输入样例】

36
3

【输出样例】

108
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1e5+10;

int A[N],B[N],C[N];
int la,lb,lc;

void mul(int A[],int B[],int C[])
{
    for(int i=0;i<la;i++)
        for(int j=0;j<lb;j++)
        {
            C[i+j]+=A[i]*B[j];
            C[i+j+1]+=C[i+j]/10;
            C[i+j]%=10;
        }
    while(lc&&C[lc]==0) lc--;
}

int main()
{
    string a,b;
    cin>>a>>b;
    la=a.size();
    lb=b.size();
    lc=la+lb+10;
    for(int i=a.size()-1;i>=0;i--) A[la-i-1]=a[i]-'0';
    for(int i=b.size()-1;i>=0;i--) B[lb-i-1]=b[i]-'0';
    mul(A,B,C);
    for(int i=lc;i>=0;i--) cout<<C[i];
    return 0;
}

 2.高精度除法

【题目描述】

高精除以高精,求它们的商和余数。

【输入】

输入两个低于300位的正整数。

【输出】

输出商和余数。

【输入样例】

1231312318457577687897987642324567864324567876543245671425346756786867867867
1231312318767141738178325678412414124141425346756786867867867

【输出样例】

999999999748590
179780909068307566598992807564736854549985603543237528310337
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

bool cmp(vector<int> &A, vector<int> &B){
    if(A.size()!=B.size()) return A.size()>B.size();
    for(int i=A.size()-1;i>=0;i--){
        if(A[i]!=B[i]) return A[i]>B[i]; 
    }
    return true;
}

vector<int> sub(vector<int> &A,vector<int> &B){
    vector<int> C;
    int t=0;
    for(int i=0;i<A.size()||t;i++){
        t = A[i] - t;
        if(i<B.size()) t -= B[i];
        C.push_back((t+10)%10);
        if(t<0) t = 1;
        else t = 0;
    }
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

vector<int> div(vector<int> &A, vector<int> &B, vector<int> &r){
    vector<int> C;
    int j = B.size();
    r.assign(A.end()-j,A.end());
    while(j<=A.size()){
        int k=0;
        while(cmp(r,B)){
            vector<int> s = sub(r,B);
            r.clear();
            r.assign(s.begin(),s.end());
            k++;
        }
        C.push_back(k);
        if(j<A.size()) r.insert(r.begin(),A[A.size()-j-1]);
        if(r.size()>1&&r.back()==0) r.pop_back();
        j++;
    }
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

int main(){
    string a,b;
    cin>>a>>b;
    vector<int> A,B,r;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');

    auto C = div(A,B,r);
    for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
    printf("\n");
    for(int i=r.size()-1;i>=0;i--) printf("%d",r[i]);
    return 0;
}

3.大整数加法

【题目描述】

求两个不超过200位的非负整数的和。

【输入】

有两行,每行是一个不超过200位的非负整数,可能有多余的前导0。

【输出】

一行,即相加后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

【输入样例】

22222222222222222222
33333333333333333333

【输出样例】

55555555555555555555
#include<bits/stdc++.h>
using namespace std;
vector<int> sum(vector<int> &A,vector<int> &B) {
    vector<int> C;
    int t=0;
    for(int i=0;i<max(A.size(),B.size());i++) {
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        C.push_back(t%10);
        t/=10;
    }
    if(t) C.push_back(1);
    while(C[C.size()-1]==0) C.pop_back();
    return C;
}
signed main() {
    vector<int> A,B;
    string a,b;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
    auto C=sum(A,B);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    return 0;
}

4.大整数减法

【题目描述】

求两个大的正整数相减的差。

【输入】

共2行,第1行是被减数a,第2行是减数b(a > b)。每个大整数不超过200位,不会有多余的前导零。

【输出】

一行,即所求的差。

【输入样例】

9999999999999999999999999999999999999
9999999999999

【输出样例】

9999999999999999999999990000000000000
#include<bits/stdc++.h>
using namespace std;
vector<int> solve(vector<int> &A,vector<int> &B) {
    vector<int> C;
    int t=0;
    for(int i=0;i<A.size();i++) {
        t+=A[i];
        if(i<B.size()) t-=B[i];
        if(t<0) {
            t+=10;
            A[i+1]--;
        }
        C.push_back(t%10);
        t/=10;
    }
    while(C[C.size()-1]==0) C.pop_back();
    return C;
}
signed main() {
    string a,b;
    vector<int> A,B;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
    vector<int> C=solve(A,B);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    return 0;
}

5.计算2的N次方

【题目描述】

任意给定一个正整数N(N<=100),计算2的n次方的值。

【输入】

输入一个正整数N。

【输出】

输出2的N次方的值。

【输入样例】

5

【输出样例】

32

高精度阶乘的变形。

#include<bits/stdc++.h>
using namespace std;
int n;
void solve() {
    vector<int> c;
    c.push_back(1);
    for(int i=1;i<=n;i++) {
        int t=0;
        for(int j=0;j<c.size();j++) {
            t+=c[j]*2;
            c[j]=t%10;
            t/=10;
        }
        if(t) c.push_back(t);
    }
    while(c[c.size()-1]==0) c.pop_back();
    for(int i=c.size()-1;i>=0;i--) cout<<c[i];
}
signed main() {
    cin>>n;
    solve();
    return 0;
}

6.大整数的因子

【题目描述】

已知正整数k满足2≤k≤9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k。

【输入】

一个非负整数c,c的位数≤30。

【输出】

若存在满足 c%k == 0 的k,从小到大输出所有这样的k,相邻两个数之间用单个空格隔开;若没有这样的k,则输出"none"。

【输入样例】

30

【输出样例】

2 3 5 6
#include<bits/stdc++.h>
using namespace std;
vector<int> A;
void solve(vector<int> &A,int B,int &r) {
    vector<int> C;
    for(int i=0;i<A.size();i++) {
        r=r*10+A[i];
        C.push_back(r/B);
        r%=B;
    }
    /*reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();*/
}
signed main() {
    string a;
    cin>>a;
    vector<int> A;
    for(int i=0;i<a.size();i++) A.push_back(a[i]-'0');
    vector<int> C=A;
    bool flag=false;
    for(int i=2;i<=9;i++) {
        int r=0;
        solve(A,i,r);
        A=C;
        if(r==0) {
            flag=true;
            cout<<i<<" ";
        }
    }
    if(!flag) cout<<"none";
    return 0;
}

 7.求10000以内n的阶乘

【题目描述】

求10000以内n的阶乘。

【输入】

只有一行输入,整数n(0≤n≤10000)。

【输出】

一行,即n!的值。

【输入样例】

4

【输出样例】

24
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
void solve() {
    cin>>n;
    vector<int> c;
    c.push_back(1);
    for(int i=1;i<=n;i++) {
        int t=0;
        for(int j=0;j<c.size();j++) {
            t+=c[j]*i;
            c[j]=t%10;
            t/=10;
        }
        while(t) {
            c.push_back(t%10);
            t/=10;
        }
    }
    for(int i=c.size()-1;i>=0;i--) cout<<c[i];
}
signed main() {
    solve();
    return 0;
}

8.阶乘和

 

【题目描述】

用高精度计算出S=1!+2!+3!+…+n!(n≤100),其中“!”表示阶乘,例如:5!=5×4×3×2×1。

输入正整数n,输出计算结果S。

【输入】

一个正整数n。

【输出】

计算结果S。

【输入样例】

5

【输出样例】

153

 

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n;
vector<int> f(int n) {
	vector<int> v;
	v.push_back(1);
	for(int i=1;i<=n;i++) {
		int t=0;
		for(int j=0;j<v.size();j++) {
			t+=i*v[j];
			v[j]=t%10;
			t/=10;
		}
		while(t) {
            v.push_back(t%10);
            t/=10;
        }
	}
	return v;
}
vector<int> sum(vector<int> &A,vector<int> &B) {
	vector<int> C;
	int t=0;
	for(int i=0;i<max(A.size(),B.size());i++) {
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(t);
	return C;
}
signed main() {
	cin>>n;
	vector<int> ans;
	for(int i=1;i<=n;i++) {
		auto x=f(i);
		ans=sum(ans,x);
	}
	for(int i=ans.size()-1;i>=0;i--) {
		cout<<ans[i];
	}
	return 0;
}

9.大整数乘法

【题目描述】

求两个不超过200位的非负整数的积。

【输入】

有两行,每行是一个不超过200位的非负整数,没有多余的前导0。

【输出】

一行,即相乘后的结果。结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342。

【输入样例】

12345678900
98765432100

【输出样例】

1219326311126352690000
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1e5+10;

int A[N],B[N],C[N];
int la,lb,lc;

void mul(int A[],int B[],int C[])
{
    for(int i=0;i<la;i++)
        for(int j=0;j<lb;j++)
        {
            C[i+j]+=A[i]*B[j];
            C[i+j+1]+=C[i+j]/10;
            C[i+j]%=10;
        }
    while(lc&&C[lc]==0) lc--;
}

int main()
{
    string a,b;
    cin>>a>>b;
    la=a.size();
    lb=b.size();
    lc=la+lb+10;
    for(int i=a.size()-1;i>=0;i--) A[la-i-1]=a[i]-'0';
    for(int i=b.size()-1;i>=0;i--) B[lb-i-1]=b[i]-'0';
    mul(A,B,C);
    for(int i=lc;i>=0;i--) cout<<C[i];
    return 0;
}

 10.除以13

【题目描述】

输入一个大于0的大整数N,长度不超过100位,要求输出其除以13得到的商和余数。

【输入】

一个大于0的大整数,长度不超过100位。

【输出】

两行,分别为整数除法得到的商和余数。

【输入样例】

2132104848488485

【输出样例】

164008065268345
0
#include<bits/stdc++.h>
using namespace std;
vector<int> A;
void solve(vector<int> &A,int B,int &r) {
    vector<int> C;
    for(int i=0;i<A.size();i++) {
        r=r*10+A[i];
        C.push_back(r/B);
        r%=B;
    }
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    puts("");
    cout<<r;
}
signed main() {
    string a;
    cin>>a;
    vector<int> A;
    for(int i=0;i<a.size();i++) A.push_back(a[i]-'0');
    int B=13,r=0;
    solve(A,B,r);
    return 0;
}

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值