大整数
大整数问题的思路说白了就是把字符串反转过来,但记得要对那些短的字符串进行补零,从头开始相加。
下面是把字符串存到结构体中写的思路
首先把字符串转换成这种形式
struct bign{
long long d[maxn];
long long len;
bign()
{
fill(d,d+maxn,0);
len=0;
}
};
转换的代码
bign change(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++)
{
a.d[i]=str[a.len-i-1]-48;
}
return a;
}
大整数加法
bign add(bign a,bign b)
{
bign c;
long long carry=0;
for(long long i=0;i<a.len||i<b.len;i++)
{
long long temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
if(carry!=0)
{
c.d[c.len++]=carry;
}
return c;
}
但是把字符串存到结构体中进行运算还是有点问题的,因为c++中的结构体在内存中是存在栈内存中的,一次数组不可以开的特别大,也就是字符串的长度不可超过1e5,否则就会出问题。所以,超过1e5用下面这种写法。
//只能是两个正数相加
string add(string str1,string str2)//高精度加法
{
string str;
reverse(str1.begin(),str1.end());
reverse(str2.begin(),str2.end());
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
int maxlen=max(len1,len2);
for(int i=1en1;i<maxlen;i++)
str1+="0";
for(int i=len2;i<maxn;i++)
str2+="0";
int temp.carry;
for(int i=0;i<maxlen;i++)
{
temp=str1[i]-'0'+str2[i]-'0'+carry;
str+=(temp%10+'0');
carry=temp/10;
temp%=10;
}
if(carry!=0) str+=(carry+'0');
return str;
}
有时候做题你会遇到好多个字符串相加,但是你不可以调用多次上面的函数哦,因为时间复杂度会过大,这样就会超时,一次,你就需要改变一下了,对所有字符串反转,补零,然后再对循环len次,每一次,把所有字符串的第i都相加。自己看看这种题吧
下面给两个解决所有大整数问题的模板
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
const long long MAX=1e15;
const int maxn=1e5;
int flag;
struct bign{
long long d[maxn];
long long len;
bign()
{
fill(d,d+maxn,0);
len=0;
}
};
bign change(char str[])
{
bign a;
a.len=strlen(str);
for(int i=0;i<a.len;i++)
{
a.d[i]=str[a.len-i-1]-48;
}
return a;
}
bign add(bign a,bign b)
{
bign c;
long long carry=0;
for(long long i=0;i<a.len||i<b.len;i++)
{
long long temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
if(carry!=0)
{
c.d[c.len++]=carry;
}
return c;
}
bign sub(bign a,bign b)
{
bign c;
for(long long i=0;i<a.len||i<b.len;i++)
{
if(a.d[i]<b.d[i])
{
a.d[i+1]--;
a.d[i]+=10;
}
c.d[c.len++]=a.d[i]-b.d[i];
}
while(c.len > 1 &&c.d[c.len - 1] == 0) c.len--;
return c;
}
bign divide(bign a,int b,long long &r)
{
bign c;
c.len=a.len;
for(long long i=a.len-1;i>=0;i++)
{
r=r*10+a.d[i];
if(r<b)
c.d[i]=0;
else
{
c.d[i]=r/b;
r=r%b;
}
}
while(c.len > 1 &&c.d[c.len - 1] == 0) c.len--;
return c;
}
bign multi(bign a,long long b)
{
bign c;
long long carry=0;
for(long long i=0;i<a.len;i++)
{
long long temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
carry=temp/10;
}
while(carry!=0)
{
c.d[c.len++]=carry%10;
carry/=10;
}
while(c.len > 1 &&c.d[c.len - 1] == 0) c.len--;
return c;
}
bign multimulti(bign a,bign b)
{
bign p,c;
for(long long i=0;i<b.len;i++)
{
p=multi(a,b.d[i]);
long long t=i;
long long aa=t/15;
long long bb=t%15;
for(long long j=0;j<aa;j++)
p=multi(p,MAX);
for(long long j=0;j<bb;j++)
p=multi(p,10);
// for(int j=0;j<i;j++)
// p=multi(p,10);
c=add(c,p);
}
return c;
}
int main()
{
char str1[10010],str2[10010];
scanf("%s %s",str1,str2);
bign a=change(str1);
bign b=change(str2);
bign c=add(a,b);
for(long long i=0;i<c.len;i++)
{
cout<<c.d[c.len-1-i];
}
}
#include<stdio.h>
#include<string>
#include<string.h>
#include<iostream>
using namespace std;
//compare比较函数:相等返回0,大于返回1,小于返回-1
int compare(string str1,string str2)
{
if(str1.length()>str2.length()) return 1;
else if(str1.length()<str2.length()) return -1;
else return str1.compare(str2);
}
//高精度加法
//只能是两个正数相加
string add(string str1,string str2)//高精度加法
{
string str;
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
if(len1<len2)
{
for(int i=1;i<=len2-len1;i++)
str1="0"+str1;
}
else
{
for(int i=1;i<=len1-len2;i++)
str2="0"+str2;
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i--)
{
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0) str=char(cf+'0')+str;
return str;
}
//高精度减法
//只能是两个正数相减,而且要大减小
/*string sub(string str1,string str2)//高精度减法
{
string str;
int tmp=str1.length()-str2.length();
int cf=0;
for(int i=str2.length()-1;i>=0;i--)
{
if(str1[tmp+i]<str2[i]+cf)
{
str=char(str1[tmp+i]-str2[i]-cf+'0'+10)+str;
cf=1;
}
else
{
str=char(str1[tmp+i]-str2[i]-cf+'0')+str;
cf=0;
}
}
for(int i=tmp-1;i>=0;i--)
{
if(str1[i]-cf>='0')
{
str=char(str1[i]-cf)+str;
cf=0;
}
else
{
str=char(str1[i]-cf+10)+str;
cf=1;
}
}
str.erase(0,str.find_first_not_of('0'));//去除结果中多余的前导0
return str;
}
//高精度乘法
//只能是两个正数相乘
string mul(string str1,string str2)
{
string str;
int len1=str1.length();
int len2=str2.length();
string tempstr;
for(int i=len2-1;i>=0;i--)
{
tempstr="";
int temp=str2[i]-'0';
int t=0;
int cf=0;
if(temp!=0)
{
for(int j=1;j<=len2-1-i;j++)
tempstr+="0";
for(int j=len1-1;j>=0;j--)
{
t=(temp*(str1[j]-'0')+cf)%10;
cf=(temp*(str1[j]-'0')+cf)/10;
tempstr=char(t+'0')+tempstr;
}
if(cf!=0) tempstr=char(cf+'0')+tempstr;
}
str=add(str,tempstr);
}
str.erase(0,str.find_first_not_of('0'));
return str;
}
//高精度除法
//两个正数相除,商为quotient,余数为residue
//需要高精度减法和乘法
void div(string str1,string str2,string "ient,string &residue)
{
quotient=residue="";//清空
if(str2=="0")//判断除数是否为0
{
quotient=residue="ERROR";
return;
}
if(str1=="0")//判断被除数是否为0
{
quotient=residue="0";
return;
}
int res=compare(str1,str2);
if(res<0)
{
quotient="0";
residue=str1;
return;
}
else if(res==0)
{
quotient="1";
residue="0";
return;
}
else
{
int len1=str1.length();
int len2=str2.length();
string tempstr;
tempstr.append(str1,0,len2-1);
for(int i=len2-1;i<len1;i++)
{
tempstr=tempstr+str1[i];
tempstr.erase(0,tempstr.find_first_not_of('0'));
if(tempstr.empty())
tempstr="0";
for(char ch='9';ch>='0';ch--)//试商
{
string str,tmp;
str=str+ch;
tmp=mul(str2,str);
if(compare(tmp,tempstr)<=0)//试商成功
{
quotient=quotient+ch;
tempstr=sub(tempstr,tmp);
break;
}
}
}
residue=tempstr;
}
quotient.erase(0,quotient.find_first_not_of('0'));
if(quotient.empty()) quotient="0";
}