一般来说:
A + B: A和B的位数
小于等于$10^6$;
A - B: A和B的位数
小于等于$10^6$;
A x a: A的位数
小于等于$10^6$,a的值
小于等于$10^9$.
高精度除法不常见
- 高精度加法:
AcWing 791. 高精度加法
#include<iostream>
#include<vector>
using namespace std;
int main()
{
string s1,s2;
vector<int> a,b,c;
cin>>s1>>s2;
for(int i=s1.size()-1;i>=0;--i) a.push_back(s1[i]-'0');
for(int i=s2.size()-1;i>=0;--i) b.push_back(s2[i]-'0');
//当把string中的数字转换成整数时就是这样:-'0'!!!
int d=0;//d表示进位
for(int i=0;i<a.size()&&i<b.size();++i)
{
c.push_back((a[i]+b[i]+d)%10);
d=(a[i]+b[i]+d)/10;
}
if(a.size()>c.size())
{
for(int i=c.size();i<a.size();++i)
{
c.push_back((a[i]+d)%10);
d=(a[i]+d)/10;
}
}
if(b.size()>c.size())
{
for(int i=c.size();i<b.size();++i)
{
c.push_back((b[i]+d)%10);
d=(b[i]+d)/10;
}
}
if(d) c.push_back(d);//最后还有进位时
for(int i=c.size()-1;i>=0;--i)//倒序输出
cout<<c[i];
return 0;
}
y总的:
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int> &A, vector<int> &B)
{
if (A.size() < B.size()) return add(B, A);//这个地方牛逼!!!
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++ )
{
t += A[i];
if (i < B.size()) t += B[i];//这个地方也牛逼!!!
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(1);
return C;
}
int 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=add(A,B);
auto C=add(A,B);//等价于vector<int> C=add(A,B).这个auto就是会自动匹配类型,因为add()函数的返回值是vector<int>类型的,所以就自动给C匹配成vector<int>类型的
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
return 0;
}
- 高精度减法:
AcWing 792. 高精度减法
减法和加法略有不同,当len(s1)>len(s2)的时候,一定有s1>s2,这时进行正常的s1-s2竖式运算模拟就行;当len(s1)<
len(s2),此时一定有s1<
s2,这时需要swap(s1,s2),此时一定有s1>s2,再进行s1-s2竖式运算模拟,然后对最后结果加上-负号就好了.还有一种情况就是len(s1)=len(s2),但s1<s2,此时需要进行swap(s1,s2),再进行s1-s2竖式运算模拟.但是这种通过判断len(s1)和len(s2)不能确定s1,s2的大小了,而且也想不到别的方法来判断,给挡在这了.
看了y总代码后发现其实很简单,只需要判断s1<s2就好了,是自己忘了两个字符串比较的含义了,下面来回顾一下:
两个字符串比较大小,当第一次出现在相同位置两个字符不相等时,两个字符中ASCII大的所在字符串就大
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int> &a,vector<int> &b)
{
vector<int> c;
int d=0;
for(int i=0;i<a.size();++i)
{
if(i<b.size())
{
if(a[i]-b[i]-d<0)
{
c.push_back(10+a[i]-b[i]-d);
d=1;
}
else
{
c.push_back(a[i]-b[i]-d);
d=0;
}
}
else
{
if(a[i]-d<0)
{
c.push_back(10+a[i]-d);
d=1;
}
else
{
c.push_back(a[i]-d);
d=0;
}
}
}
return c;
}
int main()
{
bool st;
string s1,s2;
cin>>s1>>s2;
vector<int>a,b;
if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2))
{
swap(s1,s2);
st=true;
}//这一块很有必要,可以写几个样例试试看:8888 99999;8888 9999等
for(int i=s1.size()-1;i>=0;--i) a.push_back(s1[i]-'0');
for(int i=s2.size()-1;i>=0;--i) b.push_back(s2[i]-'0');
vector<int> c=add(a,b);
while(true)
{
if(c.size()==1) break;
if(c[c.size()-1]==0) c.pop_back();
else break;
}
if(st) cout<<"-";
for(int i=c.size()-1;i>=0;--i)
cout<<c[i];
return 0;
}
刚开始的时候没有写while(true){…}这个语句,当输入111 111时输出000,这肯定不对,而且输入11 12时输出-01,所以要将后边的0给清一清
y总代码:
#include<iostream>
#include<vector>
using namespace std;
//判断是否有A>=B
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;
}
//C=A-B
vector<int> sub(vector<int> &A,vector<int> &B)
{
vector<int> C;
for(int i=0,t=0;i<A.size();++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;
}
int 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');
if(cmp(A,B))
{
vector<int> C=sub(A,B);
for(int i=C.size()-1;i>=0;--i) cout<<C[i];
}
else
{
vector<int> C=sub(B,A);
cout<<"-";
for(int i=C.size()-1;i>=0;--i) cout<<C[i];
}
return 0;
}
- 高精度乘法:
高精度乘法还是模拟我们列竖式的过程:
#include<iostream>
#include<vector>
using namespace std;
vector<int> mul(vector<int> &a,vector<int> &b)
{
vector<int> d[5];
vector<int> c;
for(int i=0;i<b.size();++i)
{
for(int k=0;k<i;++k)
d[i].push_back(0);//将尾部进行加零处理
int t=0;
for(int j=0;j<a.size();++j)
{
d[i].push_back((b[i]*a[j]+t)%10);
t=(b[i]*a[j]+t)/10;
}
if(t) d[i].push_back(t);
}//将b的每一位与a的每一位相乘
for(int i=0;i<b.size()-1;++i)
{
for(int j=d[i].size();j<d[b.size()-1].size();++j)
d[i].push_back(0);
}//将每行尾部进行加零
int t=0;
for(int i=0;i<d[b.size()-1].size();++i)
{
int sum=0;
for(int j=0;j<b.size();++j)
{
sum+=d[j][i];
}
c.push_back((sum+t)%10);
t=(sum+t)/10;
}//执行的是相加处理
if(t) c.push_back(t);
return c;
}
int main()
{
string s1,s2;
vector<int> a,b,c;
cin>>s1>>s2;
if(s1=="0"||s2=="0")
{
cout<<0;
return 0;
}
for(int i=s1.size()-1;i>=0;--i) a.push_back(s1[i]-'0');
for(int i=s2.size()-1;i>=0;--i) b.push_back(s2[i]-'0');
if(a.size()<b.size()) c=mul(b,a);
else c=mul(a,b);//习惯上len(a)>len(b)
for(int i=c.size()-1;i>=0;--i)
cout<<c[i];
return 0;
}
其实上边思路自己想复杂了,对于b其实不用挨个拆开运算,完全可以把b看成一个整体
y总
#include<iostream>
#include<vector>
using namespace std;
vector<int> mul(vector<int> &a,int num)
{
vector<int> c;
int t=0;
for(int i=0;i<a.size();++i)
{
c.push_back((a[i]*num+t)%10);
t=(a[i]*num+t)/10;
}
if(t) c.push_back(t);
return c;
}
int main()
{
string s;
int num;
cin>>s>>num;
vector<int> a;
if(num==0)
{
cout<<0;
return 0;
}
for(int i=s.size()-1;i>=0;--i) a.push_back(s[i]-'0');
vector<int> b;
b=mul(a,num);
for(int i=b.size()-1;i>=0;--i) cout<<b[i];
return 0;
}
习题:
归根结底还是用到最上边高精度加法的核心代码,只不过是涉及到多组输入
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int> &a,vector<int> &b)
{
vector<int> c;
if(a.size()<b.size())
swap(a,b);
int t=0;
for(int i=0;i<a.size();++i)
{
t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t%10);
t/=10;
}
if(t) c.push_back(1);
return c;
}
int main()
{
int n;
string s;
vector<int>a,b;
cin>>n;
getchar();
while(n--)
{
a.clear();b.clear();//每组都要清空
while(cin>>s&&s!="0")
{
if(s=="") continue;
if(a.empty())
for(int i=s.size()-1;i>=0;--i) a.push_back(s[i]-'0');
else
{
for(int i=s.size()-1;i>=0;--i) b.push_back(s[i]-'0');
a=add(a,b);
}
b.clear();//输入一组后必须要清空
}
for(int i=a.size()-1;i>=0;--i)
cout<<a[i];
cout<<endl;
if(n) cout<<endl;
}
return 0;
}
刚开始思路这样,输入数据测试都对,但提交就是WA
看了看其他通过代码后发现了问题,原来是漏了一组情况,当输入的数是0 0时应该输出0,但我上边的思路是什么也不输出.所以就要特判这种情况
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int> &a,vector<int> &b)
{
vector<int> c;
if(a.size()<b.size())
swap(a,b);
int t=0;
for(int i=0;i<a.size();++i)
{
t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t%10);
t/=10;
}
if(t) c.push_back(1);
return c;
}
int main()
{
int n;
string s;
vector<int>a,b;
cin>>n;
getchar();
while(n--)
{
a.clear();b.clear();//每组都要清空
int num=0;
while(cin>>s&&s!="0")
{
num++;
if(s=="") continue;
if(a.empty())
for(int i=s.size()-1;i>=0;--i) a.push_back(s[i]-'0');
else
{
for(int i=s.size()-1;i>=0;--i) b.push_back(s[i]-'0');
a=add(a,b);
}
b.clear();//输入一组后必须要清空
}
if(s=="0"&&num==0) cout<<"0";
else
{
for(int i=a.size()-1;i>=0;--i)
cout<<a[i];
}
cout<<endl;
if(n) cout<<endl;
}
return 0;
}
这样就可以了,hdu上的题真有点恶心…
- HDU.1042 N!
百度可知10000!是有 35660 位数