在 C++ 中,long long 都无法表示我们需要的整数时怎么办?那就用高精度吧!
A+B Problem(高精)
题目描述
高精度加法,相当于 a+b problem,不用考虑负数。
输入格式
分两行输入。 a , b ≤ 1 0 500 a,b \leq 10^{500} a,b≤10500。
输出格式
输出只有一行,代表 a + b a+b a+b 的值。
样例 #1
样例输入 #1
1
1
样例输出 #1
2
样例 #2
样例输入 #2
1001
9099
样例输出 #2
10100
提示
20 % 20\% 20% 的测试数据, 0 ≤ a , b ≤ 1 0 9 0\le a,b \le10^9 0≤a,b≤109;
40 % 40\% 40% 的测试数据, 0 ≤ a , b ≤ 1 0 18 0\le a,b \le10^{18} 0≤a,b≤1018。
代码实现
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class BigInt:public vector<int>
{
public:
BigInt(){push_back(0);}
BigInt(string s)
{
for(int i=s.size()-1;i>=0;i--)push_back(s[i]-'0');
proccess_digit();
}
BigInt&operator+=(const BigInt&a)
{
for(int i=0;i<a.size();i++)
{
if(i>=size())push_back(0);
at(i)+=a[i];
}
proccess_digit();
return *this;
}
void proccess_digit()
{
for(int i=0;i<size();i++)
{
if(at(i)<10)continue;
if(i==size()-1)push_back(0);
at(i+1)+=at(i)/10;
at(i)%=10;
}
return ;
}
};
ostream&operator<<(ostream&out,BigInt&a)
{
for(int i=a.size()-1;i>=0;i--)
out<<a[i];
return out;
}
int main()
{
string s;
cin>>s;
BigInt a(s);
cin>>s;
BigInt b(s);
a+=b;
cout<<a;
return 0;
}
高精度减法
题目描述
高精度减法。
输入格式
两个整数 a , b a,b a,b(第二个可能比第一个大)。
输出格式
结果(是负数要输出负号)。
样例 #1
样例输入 #1
2
1
样例输出 #1
1
提示
- 20 % 20\% 20% 数据 a , b a,b a,b 在 long long 范围内;
- 100 % 100\% 100% 数据 0 < a , b ≤ 1 0 10086 0<a,b\le 10^{10086} 0<a,b≤1010086。
代码实现
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class BigInt:public vector<int>
{
public:
BigInt(){push_back(0);}
BigInt(string s){
for(int i=s.size()-1;i>=0;i--)
push_back(s[i]-'0');
}
BigInt&operator-=(BigInt&a)
{
for(int i=0;i<a.size();i++)
at(i)-=a[i];
proccess_digit();
return *this;
}
void proccess_digit()
{
for(int i=0;i<size();i++)
{
if(at(i)>=0)continue;
at(i+1)-=1;
at(i)+=10;
}
return ;
}
};
bool compare(const BigInt&a,const BigInt&b)
{
if(a.size()!=b.size())return a.size()>b.size();
else{
for(int i=a.size()-1;i>=0;i--)
{
if(a[i]>b[i])return 1;
if(a[i]<b[i])return 0;
}
}
return 1;
}
ostream&operator<<(ostream&out,BigInt a)
{
int flag=1;
for(int i=a.size()-1;i>=0;i--)
{
if(flag&&!a[i])continue;
out<<a[i];
flag=0;
}
if(flag)cout<<0;
return out;
}
int main()
{
string s;
cin>>s;
BigInt a(s);
cin>>s;
BigInt b(s);
if(compare(a,b))
{
a-=b;
cout<<a;
}
else{
cout<<'-';
b-=a;
cout<<b;
}
return 0;
}
A*B Problem
题目背景
高精度乘法模板题。
题目描述
给出两个非负整数,求它们的乘积。
输入格式
输入共两行,每行一个非负整数。
输出格式
输出一个非负整数表示乘积。
样例 #1
样例输入 #1
1
2
样例输出 #1
2
提示
每个非负整数不超过 1 0 2000 10^{2000} 102000。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class BigInt:public vector<int>
{
public:
BigInt(){push_back(0);}
BigInt(string s){
for(int i=s.size()-1;i>=0;i--)
push_back(s[i]-'0');
}
BigInt operator*(const BigInt&a)
{
BigInt c;
for(int i=0;i<size();i++)
{
for(int j=0;j<a.size();j++)
{
if(i+j>=c.size())c.push_back(0);
c.at(i+j)+=at(i)*a[j];
}
}
c.proccess_digit();
return c;
}
BigInt&operator=(const BigInt&a)
{
for(int i=0;i<a.size();i++)
{
if(i>=size())push_back(0);
at(i)=a[i];
}
for(int i=a.size();i<size();i++)erase(begin()+i);
return *this;
}
BigInt&operator*=(const BigInt&a)
{
*this=(*this)*a;
return *this;
}
void proccess_digit()
{
for(int i=0;i<size();i++)
{
if(at(i)<10)continue;
if(i==size()-1)push_back(0);
at(i+1)+=at(i)/10;
at(i)%=10;
}
return ;
}
};
ostream&operator<<(ostream&out,BigInt&a)
{
int flag=1;
for(int i=a.size()-1;i>=0;i--)
{
if(flag&&!a[i])continue;
out<<a[i];
flag=0;
}
if(flag)out<<0;
return out;
}
int main()
{
string s;
cin>>s;
BigInt a(s);
cin>>s;
BigInt b(s);
a*=b;
cout<<a;
return 0;
}
A/B Problem
题目描述
输入两个整数 a , b a,b a,b,输出它们的商。
输入格式
两行,第一行是被除数,第二行是除数。
输出格式
一行,商的整数部分。
样例 #1
样例输入 #1
10
2
样例输出 #1
5
提示
0 ≤ a ≤ 1 0 5000 0\le a\le 10^{5000} 0≤a≤105000, 1 ≤ b ≤ 1 0 9 1\le b\le 10^9 1≤b≤109。
代码实现
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class BigInt:public vector<int>
{
public:
BigInt(){push_back(0);}
BigInt(string s){
for(int i=s.size()-1;i>=0;i--)
push_back(s[i]-'0');
}
BigInt operator/(int x)
{
BigInt ret(*this);
long long now=0;
for(int i=size()-1;i>=0;i--)
{
now=10*now+at(i);
ret[i]=now/x;
now%=x;
}
return ret;
}
BigInt&operator/=(int x)
{
*this=(*this)/x;
return *this;
}
};
ostream&operator<<(ostream&out,BigInt&a)
{
int flag=1;
for(int i=a.size()-1;i>=0;i--)
{
if(flag&&!a[i])continue;
out<<a[i];
flag=0;
}
if(flag)out<<0;
return out;
}
int main()
{
string s;
int b;
cin>>s;
BigInt a(s);
cin>>b;
a/=b;
cout<<a;
return 0;
}
[NOIP1998 普及组] 阶乘之和
题目描述
用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!+⋯+n!( n ≤ 50 n \le 50 n≤50)。
其中 !
表示阶乘,定义为
n
!
=
n
×
(
n
−
1
)
×
(
n
−
2
)
×
⋯
×
1
n!=n\times (n-1)\times (n-2)\times \cdots \times 1
n!=n×(n−1)×(n−2)×⋯×1。例如,
5
!
=
5
×
4
×
3
×
2
×
1
=
120
5! = 5 \times 4 \times 3 \times 2 \times 1=120
5!=5×4×3×2×1=120。
输入格式
一个正整数 n n n。
输出格式
一个正整数 S S S,表示计算结果。
样例 #1
样例输入 #1
3
样例输出 #1
9
提示
【数据范围】
对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50。
【其他说明】
注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n ≤ 20 n \le 20 n≤20,使用书中的代码无法通过本题。
如果希望通过本题,请继续学习第八章高精度的知识。
NOIP1998 普及组 第二题
代码实现
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class BigInt:public vector<int>
{
public:
BigInt(){push_back(0);}
BigInt(string s){
for(int i=s.size()-1;i>=0;i--)
push_back(s[i]-'0');
}
BigInt&operator+=(const BigInt&a)
{
for(int i=0;i<a.size();i++)
{
if(i>=size())push_back(0);
at(i)+=a[i];
}
proccess_digit();
return *this;
}
BigInt&operator*=(int a)
{
for(int i=0;i<size();i++)
at(i)*=a;
proccess_digit();
return *this;
}
void proccess_digit()
{
for(int i=0;i<size();i++)
{
if(at(i)<10)continue;
if(i==size()-1)push_back(0);
at(i+1)+=at(i)/10;
at(i)%=10;
}
return ;
}
};
ostream&operator<<(ostream&out,BigInt&a)
{
int flag=1;
for(int i=a.size()-1;i>=0;i--)
{
if(flag&&!a[i])continue;
out<<a[i];
flag=0;
}
if(flag)out<<0;
return out;
}
int main()
{
int n;
cin>>n;
string a="1";
BigInt ans,t(a);
for(int i=1;i<=n;i++)
{
t*=i;
ans+=t;
}
cout<<ans;
return 0;
}