更新:高效大数模板
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<queue>
using namespace std;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
#define arrLen 50050 // 数组长度
class BigNum
{
private:
int a[arrLen]; //可以控制大数的位数
int len; //大数长度
public:
BigNum(){ len = 1;memset(a,0,sizeof(a)); } //构造函数
BigNum(const int); //将一个int类型的变量转化为大数
BigNum(const char*); //将一个字符串类型的变量转化为大数
BigNum(const BigNum &); //拷贝构造函数
BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算
friend istream& operator>>(istream&, BigNum&); //重载输入运算符
friend ostream& operator<<(ostream&, BigNum&); //重载输出运算符
BigNum operator+(const BigNum &) const; //重载加法运算符,两个大数之间的相加运算
BigNum operator-(const BigNum &) const; //重载减法运算符,两个大数之间的相减运算
BigNum operator*(const BigNum &) const; //重载乘法运算符,两个大数之间的相乘运算
BigNum operator/(const int &) const; //重载除法运算符,大数对一个整数进行相除运算
BigNum operator^(const int &) const; //大数的n次方运算
int operator%(const int &) const; //大数对一个int类型的变量进行取模运算
bool operator>(const BigNum & T)const; //大数和另一个大数的大小比较
bool operator>(const int & t)const; //大数和一个int类型的变量的大小比较
void print(); //输出大数
};
BigNum::BigNum(const int b) //将一个int类型的变量转化为大数
{
int c,d = b;
len = 0;
memset(a,0,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s) //将一个字符串类型的变量转化为大数
{
int t,k,index,l,i;
memset(a,0,sizeof(a));
l=strlen(s);
len=l/DLEN;
if(l%DLEN)
len++;
index=0;
for(i=l-1;i>=0;i-=DLEN)
{
t=0;
k=i-DLEN+1;
if(k<0)
k=0;
for(int j=k;j<=i;j++)
t=t*10+s[j]-'0';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len) //拷贝构造函数
{
int i;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = T.a[i];
}
BigNum & BigNum::operator=(const BigNum & n) //重载赋值运算符,大数之间进行赋值运算
{
int i;
len = n.len;
memset(a,0,sizeof(a));
for(i = 0 ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
istream& operator>>(istream & in, BigNum & b) //重载输入运算符
{
char ch[MAXSIZE*4];
int i = -1;
in>>ch;
int l=strlen(ch);
int count=0,sum=0;
for(i=l-1;i>=0;)
{
sum = 0;
int t=1;
for(int j=0;j<4&&i>=0;j++,i--,t*=10)
{
sum+=(ch[i]-'0')*t;
}
b.a[count]=sum;
count++;
}
b.len =count++;
return in;
}
ostream& operator<<(ostream& out, BigNum& b) //重载输出运算符
{
int i;
cout << b.a[b.len - 1];
for(i = b.len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum & T) const //两个大数之间的相加运算
{
BigNum t(*this);
int i,big; //位数
big = T.len > len ? T.len : len;
for(i = 0 ; i < big ; i++)
{
t.a[i] +=T.a[i];
if(t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -=MAXN+1;
}
}
if(t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum & T) const //两个大数之间的相减运算
{
int i,j,big;
bool flag;
BigNum t1,t2;
if(*this>T)
{
t1=*this;
t2=T;
flag=0;
}
else
{
t1=T;
t2=*this;
flag=1;
}
big=t1.len;
for(i = 0 ; i < big ; i++)
{
if(t1.a[i] < t2.a[i])
{
j = i + 1;
while(t1.a[j] == 0)
j++;
t1.a[j--]--;
while(j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while(t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if(flag)
t1.a[big-1]=0-t1.a[big-1];
return t1;
}
BigNum BigNum::operator*(const BigNum & T) const //两个大数之间的相乘运算
{
BigNum ret;
int i,j,up;
int temp,temp1;
for(i = 0 ; i < len ; i++)
{
up = 0;
for(j = 0 ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if(up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int & b) const //大数对一个整数进行相除运算
{
BigNum ret;
int i,down = 0;
for(i = len - 1 ; i >= 0 ; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while(ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator %(const int & b) const //大数对一个int类型的变量进行取模运算
{
int i,d=0;
for (i = len-1; i>=0; i--)
{
d = ((d * (MAXN+1))% b + a[i])% b;
}
return d;
}
BigNum BigNum::operator^(const int & n) const //大数的n次方运算
{
BigNum t,ret(1);
int i;
if(n<0)
exit(-1);
if(n==0)
return 1;
if(n==1)
return *this;
int m=n;
while(m>1)
{
t=*this;
for( i=1;i<<1<=m;i<<=1)
{
t=t*t;
}
m-=i;
ret=ret*t;
if(m==1)
ret=ret*(*this);
}
return ret;
}
bool BigNum::operator>(const BigNum & T) const //大数和另一个大数的大小比较
{
int ln;
if(len > T.len)
return true;
else if(len == T.len)
{
ln = len - 1;
while(a[ln] == T.a[ln] && ln >= 0)
ln--;
if(ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator >(const int & t) const //大数和一个int类型的变量的大小比较
{
BigNum b(t);
return *this>b;
}
void BigNum::print() //输出大数
{
int i;
cout << a[len - 1];
for(i = len - 2 ; i >= 0 ; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
char s[arrLen],s1[arrLen];
int main(void)
{
int i,n;
//定义大数的对象数组
while(scanf("%s%s",s,s1)!=EOF){
BigNum a(s),b(s1);
a=a*b;
a.print();
};
}
大数加法1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void add(char a[],char b[],char back[])
{
int i,j,k,up,x,y,z,l;
char *c;
if(strlen(a) > strlen(b))
l = strlen(a)+2;
else
l = strlen(b)+2;
c = (char*)malloc(l*sizeof(char));
i = strlen(a)-1;
j = strlen(b)-1;
k = 0;
up = 0;
while(j>=0 || i>=0)
{
if(i<0) x = '0';
else
x = a[i];
if(j<0) y = '0';
else
y = b[j];
z = x-'0'+y-'0';
if(up)
z++;
if(z>9)
{
up = 1;
z%=10;
}
else
up = 0;
c[k++] = z+'0';
i--;
j--;
}
if(up)
c[k++] = '1';
i = 0;
c[k] = '\0';
for(k-=1; k>=0; k--)
back[i++] = c[k];
back[i] = '\0';
}
int main()
{
char c[10000],t[10000],sum[1000];
int m;
scanf("%d%*c",&m);
while(m--)
{
scanf("%s%s",c,t);
add(c,t,sum);
printf("%s\n",sum);
if(m)
printf("\n");
}
return 0;
}
大数加法2
void Add(char *str1, char *str2, char *str3)
{ // str3 = str1 + str2;
int i, j, i1, i2, tmp, carry;
int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
char ch;
i1 = len1 - 1;
i2 = len2 - 1;
j = carry = 0;
for (; i1 >= 0 && i2 >= 0; ++j, --i1, --i2)
{
tmp = str1[i1] - '0' + str2[i2] - '0' + carry;
carry = tmp / 10;
str3[j] = tmp % 10 + '0';
}
while (i1 >= 0)
{
tmp = str1[i1--] - '0' + carry;
carry = tmp / 10;
str3[j++] = tmp % 10 + '0';
}
while (i2 >= 0)
{
tmp = str2[i2--] - '0' + carry;
carry = tmp / 10;
str3[j++] = tmp % 10 + '0';
}
if (carry)
{
str3[j++] = carry + '0';
}
str3[j] = '\0';
for (i = 0, --j; i < j; ++i, --j)
{
ch = str3[i];
str3[i] = str3[j];
str3[j] = ch;
}
return;
}
大数减法
void Minus(char *str1, char *str2, char *str3)
{ // str3 = str1-str2 (str1 > str2)
int i, j, i1, i2, tmp, carry;
int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
char ch;
i1 = len1 - 1;
i2 = len2 - 1;
j = carry = 0;
while (i2 >= 0)
{
tmp = str1[i1] - str2[i2] - carry;
if (tmp < 0)
{
str3[j] = tmp + 10 + '0';
carry = 1;
}
else
{
str3[j] = tmp + '0';
carry = 0;
}
i1--;
i2--;
j++;
}
while (i1 >= 0)
{
tmp = str1[i1] - '0' - carry;
if (tmp < 0)
{
str3[j] = tmp + 10 + '0';
carry = 1;
}
else
{
str3[j] = tmp + '0';
carry = 0;
}
--i1;
++j;
}
--j;
while (str3[j] == '0' && j > 0)
{
--j;
}
str3[++j] = '\0';
for (i = 0, --j; i < j; ++i, --j)
{
ch = str3[i];
str3[i] = str3[j];
str3[j] = ch;
}
return;
}
大数乘以小数
#include <stdio.h>
#include <string.h>
void mult(char c[],int m,char t[])
{
char s[100];
int len=strlen(c);
for(int i=0; i<len; i++)
s[len-i-1]=c[i]-'0';
int flag,add=0;
for(int i=0; i<len; i++)
{
int k=s[i]*m+add;
if(k>=10)
{
s[i]=k%10;
add=k/10;
flag=1;
}
else
{
s[i]=k;
add=0;
flag=0;
}
}
while(add)
{
s[len++]=add%10;
add/=10;
}
for(int i=0; i<len; i++)
t[len-1-i]=s[i]+'0';
t[len]='\0';
}
//大数加小数
void addt(char a[],int b,char c[])
{
int len=strlen(a);
char s[100];
for(int i=0; i<len; i++)
s[len-i-1]=a[i]-'0';
int add=0;
for(int i=0;; i++)
{
if(i>=len)
{
s[i]=0;
len++;
}
int k=s[i]+b%10+add;
b/=10;
if(k>=10)
{
s[i]=k%10;
add=k/10;
}
else
{
s[i]=k;
add=0;
}
if(b==0&&add==0)break;
}
for(int i=0; i<len; i++)
c[len-1-i]=s[i]+'0';
c[len]='\0';
}
int main()
{
char c[1000],t[1000],sum[1000];
int m;
while(~scanf("%s%d",c,&m))
{
mult(c,m,t);
printf("%s\n",t);
addt(c,m,sum);
printf("%s\n",sum);
}
return 0;
}
大数乘法
void Mul(char *str1, char *str2, char *str3)
{
int i, j = 0, i1, i2, tmp, carry, jj;
int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
char ch;
jj = carry = 0;
for (i1 = len1 - 1; i1 >= 0; --i1)
{
j = jj;
for (i2 = len2 - 1; i2 >= 0; --i2, ++j)
{
tmp = (str3[j] - '0') + (str1[i1] - '0') * (str2[i2] - '0') + carry;
if (tmp > 9)
{
carry = tmp / 10;
str3[j] = tmp % 10 + '0';
}
else
{
str3[j] = tmp + '0';
carry = 0;
}
}
if (carry)
{
str3[j] = carry + '0';
carry = 0;
j++;
}
jj++;
}
j--;
while (str3[j] == '0' && j > 0)
{
j--;
}str3[++j] = '\0';
for (i = 0, --j; i < j; ++i, --j)
{
ch = str3[i];
str3[i] = str3[j];
str3[j] = ch;
}
return;
}
大数除法
void Div(char *str1, char *str2, char *str3)
{
int i1, i2, i, j, jj = 0, tag, carry, cf, c[MAXSIZE];
int len1 = (int)strlen(str1), len2 = (int)strlen(str2), lend;
char d[MAXSIZE];
memset(c, 0, sizeof(c));
memcpy(d, str1, len2);
lend = len2;
j = 0;
for (i1 = len2 - 1; i1 < len1; ++i1)
{
if (lend < len2)
{
d[lend] = str1[i1 + 1];
c[j] = 0;
++j;
++lend;
}
else if (lend == len2)
{
jj = 1;
for (i = 0; i < lend; ++i)
{
if (d[i] > str2[i])
{
break;
}
else if (d[i] < str2[i])
{
jj = 0;
break;
}
}
if (jj == 0)
{
d[lend] = str1[i1 + 1];
c[j] = 0;
++j;
++lend;
continue;
}
}
if (jj == 1 || lend > len2)
{
cf = jj = 0;
while (d[jj] <= '0' && jj < lend)
{
++jj;
}
if (lend - jj > len2)
{
cf = 1;
}
else if (lend - jj < len2)
{
cf = 0;
}
else
{
i2 = 0;
cf = 1;
for (i = jj; i < lend; ++i)
{
if (d[i] < str2[i2])
{
cf = 0;
break;
}
else if (d[i] > str2[i2])
{
break;
}
++i2;
}
}
while (cf)
{
i2 = len2 - 1;
cf = 0;
for (i = lend - 1; i >= lend - len2; --i)
{
d[i] = d[i] - str2[i2] + '0';
if (d[i] < '0')
{
d[i] = d[i] + 10;
carry = 1;
--d[i - 1];
}
else
{
carry = 0;
}
--i2;
}
++c[j];
jj = 0;
while (d[jj] <= '0' && jj < lend)
{
++jj;
}
if (lend - jj > len2)
{
cf = 1;
}
else if (lend - jj < len2)
{
cf = 0;
}
else
{
i2 = 0;
cf = 1;
for (i = jj; i < lend; ++i)
{
if (d[i] < str2[i2])
{
cf = 0;
break;
}
else if (d[i] > str2[i2])
{
break;
}
++i2;
}
}
}
jj = 0;
while (d[jj] <= '0' && jj < lend)
{
++jj;
}
for (i = 0; i < lend - jj; ++i)
{
d[i] = d[i + jj];
}
d[i] = str1[i1 + 1];
lend = i + 1;
j++;
}
}
i = tag = 0;
while (c[i] == 0)
{
++i;
}
for (; i < j; ++i, ++tag)
{
str3[tag] = c[i] + '0';
}
str3[tag] = '\0';
return;
}
大数阶乘
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
void factorial(int n,int *) ;
int b[10000];
int n;
while(cin>>n)
{
factorial(n,b);
}
return 0;
}
void factorial(int n,int b[10000])
{
long a[10000];
int i,j,l,c,m=0,w;
a[0]=1;
for(i=1; i<=n; i++)
{
c=0;
for(j=0; j<=m; j++)
{
a[j]=a[j]*i+c;
c=a[j]/10000;
a[j]=a[j]%10000;
}
if(c>0)
{
m++;
a[m]=c;
}
}
w = m*4+log10(a[m])+1;
cout << w << endl;
cout<<a[m];
for(i=m-1; i>=0; i--)
cout<<a[i];
cout<<endl;
}
进制转换
#include <stdio.h>
#include <string.h>
void consversion(char s[],char s2[],long d1,long d2)
{
long i,j,t,num;
char c;
num = 0;
for(i = 0;s[i]!='\0';i++)
{
if(s[i]<='9' && s[i]>='0')
t = s[i] - '0';
else
t = s[i] - 'A' +10;
num = num*d1+t;
}
i = 0;
while(1)
{
t = num%d2;
if(t<=9)
s2[i] = t+'0';
else
s2[i] = t+'A'-10;
num/=d2;
if(num == 0)
break;
i++;
}
for(j = 0;j<i/2;j++)
{
c = s2[j];
s2[j] = s[i-j];
s2[i-j] = c;
}
s2[i+1]='\0';
}
int main()
{
char s1[1000],s2[1000];
int d1,d2;
while(~scanf("%s%d%d",s1,&d1,&d2))
{
consversion(s1,s2,d1,d2);
printf("%s\n",s2);
}
return 0;
}