在c中,最大的整形为long long,大于1e18左右,但是在很多时候,long long还是鞭长莫及,这个时候,我们就要用到大数来储存了。
对于每个数,我们用这个int[]来储存,第一位为符号位,1代表正,-1代表负,为了方便,后面的位是按照原数的低位到高位储存 例如246存为 1 6 4 2。
这样,管你多大的数我们都可以存下来了。
定义好了之后,就自己重载一遍所需要的运算符,bignum就可以代替int和long long了。
代码:
#include
#include
#include
#include
#define N 1001//1000位大数
using namespace std;
class BigNum
{
public:
int s[N]; //存放各位数字,s[0]为符号位,1代表正数,-1代表负数
//数组内高位存高位,123存在里面则为 1 3 2 1 ,第1个 1表示符号
int len; //长度
public:
BigNum()
{
memset(s,0,sizeof(s)); //初始化全0
s[0]=1; //默认正数
len=2; //变量初始化为0
}
int in() //输入
{
char tmp[N];
int flag=scanf("%s",tmp);
*this=tmp;
return flag;
}
void out() //输出
{
if(s[0]==-1) printf("-");
for(int i=len-1;i>0;i--)
printf("%d",s[i]);
}
void Clear()
{
memset(s,0,sizeof(s)); //初始化全0
s[0]=1; //默认正数
len=2; //变量初始化为0
}
BigNum Nizhi() //排除符号位颠倒数组
{
BigNum ans;
ans.s[0]=s[0];
for(int i=1;i<=len/2;i++)
{
ans.s[i]=s[len-i];
ans.s[len-i]=s[i];
}
ans.len=len;
return ans;
}
friend bool operator<(const BigNum &a,const BigNum &b);
friend bool operator>(const BigNum &a,const BigNum &b);
friend bool operator<=(const BigNum &a,const BigNum &b);
friend bool operator>=(const BigNum &a,const BigNum &b);
friend BigNum operator+(BigNum a,BigNum b);
friend void operator+=(BigNum &a,BigNum b);
friend BigNum operator-(BigNum a,BigNum b);
friend void operator-=(BigNum &a,BigNum b);
friend BigNum operator*(BigNum a,BigNum b);
friend void operator*=(BigNum &a,BigNum b);
friend BigNum operator/(BigNum a,BigNum b);
friend void operator/=(BigNum &a,BigNum b);
friend BigNum operator%(BigNum &a,BigNum b);
friend void operator%=(BigNum &a,BigNum b);
friend bool operator==(const BigNum &a,const BigNum &b);
void operator=(const int a);
void operator=(const char *a);
BigNum operator--();
BigNum operator--(int);
BigNum operator++();
BigNum operator++(int);
};
/////////////////////////////////////////////////////////////////逻辑//////////////////
bool operator<(const BigNum &a,const BigNum &b)
{
bool flag;
if(a.s[0]==-1&&b.s[0]==1) return 1; //如果a为负,b为正,那么a
else if(a.s[0]==1&&b.s[0]==-1) return 0; //如果a为正,b为负,那么a>b
else if(a.s[0]==1&&b.s[0]==1) flag=1; //如果a、b都为正,flag=1,表示a、b大小和符号无关
else flag=0; //如果a、b都为负,flag=0,表示a、b大小和符号有关
// flag=1 时,a、b大小和除符号外的数字大小成正比,反之反比
if(a.len>b.len) return !flag; //a的位数多,所以a大,返回0
else if(a.lenreturn flag; //a的位数少,所以a小,返回1
else
{
int i=a.len; //从最高位开始比
while(i-->1)
{
if(a.s[i]>b.s[i]) return !flag;
else if(a.s[i]return flag;
}
return 0; //没有差异即相等返回0
}
}
bool operator<=(const BigNum &a,const BigNum &b) //同 <
{
bool flag; // flag=1 表示两者都是正的 =0表示两者都是负的
if(a.s[0]==-1&&b.s[0]==1) return 1;
else if(a.s[0]==1&&b.s[0]==-1) return 0;
else if(a.s[0]==1&&b.s[0]==1) flag=1;
else flag=0;
// flag 表示1 ,!flag 表示0
if(a.len>b.len) return !flag;
else if(a.lenreturn flag;
else
{
int i=a.len;
while(i-->1)
{
if(a.s[i]>b.s[i]) return !flag;
else if(a.s[i]return flag;
}
return 1;
}
}
bool operator>(const BigNum &a,const BigNum &b)
{
return !(a<=b);
}
bool operator>=(const BigNum &a,const BigNum &b)
{
return !(abool operator==(const BigNum &a,const BigNum &b)
{
if(a.s[0]==-1&&b.s[0]==1) return 0;
else if(a.s[0]==1&&b.s[0]==-1) return 0;
if(a.len>b.len) return 0;
else if(a.lenreturn 0;
else
{
int i=a.len;
while(i-->1)
{
if(a.s[i]>b.s[i]) return 0;
else if(a.s[i]return 0;
}
return 1;
}
}
///////////////////////////////////////////////////////运算///////////////
BigNum operator-(BigNum a,BigNum b)
{
BigNum ans;
if(a.s[0]==1&&b.s[0]==-1) //如果a正,b负,那么等同于a+|b|
{
b.s[0]=1;
return a+b;
}
else if(a.s[0]==-1&&b.s[0]==1) //如果a负,b正,那么等同于-(|a|+b)
{
a.s[0]=1;
ans=a+b;
ans.s[0]=-1;
return ans;
}
else if(a.s[0]==-1&&b.s[0]==-1) //如果a负,b负,那么等同于|b|-|a|
{
a.s[0]=1;
b.s[0]=1;
return b-a;
}
else //进到这一区域的,a为正,b为正
{
if(a//如果a
{
ans=b-a;
ans.s[0]=-1;
}
else //进到这一区域a、b为正,且a>b,也就是说减出来的绝对是正数
{
int i=0;
int lm=a.len>b.len?a.len:b.len; //由于减出来必定是正数,不需要考虑lm-1位<0的情况
for(int i=1;iint tmp=ans.s[i]+a.s[i]-b.s[i];
if(tmp<0)
{
ans.s[i+1]--;
tmp+=10;
}
ans.s[i]=tmp;
}
while(lm>2) //清楚高位0,最多清楚到0为止
{
if(ans.s[lm-1]==0) lm--;
else break;
}
ans.len=lm;
}
}
return ans;
}
void operator-=(BigNum &a,BigNum b)
{
a=a-b;
}
BigNum operator+(BigNum a,BigNum b)
{
BigNum ans;
int lm=a.len>b.len?a.len:b.len;
if(a.s[0]*b.s[0]==1) //如果两者符号位相同
{
ans.s[0]=a.s[0]; //结果符号位与任意一个相同
for(int i=1;iint tmp=ans.s[i]+a.s[i]+b.s[i];
if(tmp>=10)
{
ans.s[i+1]++;
}
ans.s[i]=tmp%10;
}
if(ans.s[lm]==0) ans.len=lm; //如果最高位没有进位,那么长度不变,否则加1
else ans.len=lm+1;
}
else //如果a、b符号不同,可以转化为减法
{
if(a.s[0]==1)
{
b.s[0]=1;
return a-b;
}
else
{
a.s[0]=1;
return b-a;
}
}
return ans;
}
void operator+=(BigNum &a,BigNum b)
{
a=a+b;
}
BigNum operator*(BigNum a,BigNum b)
{
BigNum ans;
ans.s[0]=a.s[0]*b.s[0]; //乘法和除法的符号位简单处理
for(int i=1;ifor(int j=1;j1]+=a.s[i]*b.s[j]; //先存
}
}
int maxt=a.len+b.len; //最多位数
for(int i=1;i//处理每个位上的数
{
if(ans.s[i]>=10)
{
ans.s[i+1]+=ans.s[i]/10;
ans.s[i]=ans.s[i]%10;
}
}
int i;
for(i=maxt;i>1;i--) //处理高位0
{
if(ans.s[i]!=0) break;
}
ans.len=i+1;
return ans;
}
void operator*=(BigNum &a,BigNum b)
{
a=a*b;
}
BigNum operator/(BigNum a,BigNum b)
{
/*
思路: 首先从a的高位往低位数,如果还=b,然后遍历1-9,判断此时
合适取值,和平常手动计算思路一样
*/
BigNum ans;
ans.s[0]=a.s[0]*b.s[0];
b.s[0]=1; //中途比较需要
BigNum tmp; //添位取值
tmp.len=1; //刚开始为无值,就是说连a的最高位都还没纳入
BigNum zj; //中间变量,比较时需要,由于数组是倒置的,所以加这一变量
ans.len=1; //答案还是空的
int j=a.len; //j固定指向a,不断取值
bool match=1; //match为0退出循环
while(1)
{
while(1) //如果还没取够值,就继续加位
{
if(j==1) //如果a到了符号位,那么可以退出循环了
{
match=0;
break;
}
tmp.s[tmp.len++]=a.s[--j]; //加位,由于开始不好确定位数,所以直接正向不好办
zj=tmp.Nizhi(); //数组颠倒后再去比较
if(b<=zj) break; //如果b<=zj了,就可以退出了,否则该位为0
ans.s[ans.len++]=0;
}
if(!match) break; //match为0退出循环
int i;
BigNum r=b; //r为最大容许的乘后值
for(i=2;i<=10;i++)
{
BigNum p;
p.s[p.len-1]=i; //获得 2 - 10 . 赋值过程不符常规,但由于下一步是乘,可以忽略该bug
BigNum u=b*p; //如果u超过了中间变量,可以退出了,同i应该减1
if(zjbreak;
r=u; //乘得的最大数
}
i--;
ans.s[ans.len++]=i; //逐位求值
zj=zj-r; //获得余数
BigNum q;
if(zj==q) zj.len--; //如果余数为0,那么去掉,不能出现00,不然会出错
tmp=zj.Nizhi(); //重新逆置
}
ans=ans.Nizhi(); //逆置获得答案
while(ans.s[ans.len-1]==0&&ans.len>2) //高位消0
{
ans.len--;
}
return ans;
}
void operator/=(BigNum &a,BigNum b)
{
a=a/b;
}
BigNum operator%(BigNum &a,BigNum b)
{
b.s[0]=1;
BigNum tmp;
tmp.len=1;
BigNum zj;
int j=a.len;
bool match=1;
while(1)
{
while(1)
{
if(j==1)
{
match=0;
break;
}
tmp.s[tmp.len++]=a.s[--j];
zj=tmp.Nizhi();
if(b<=zj) break;
}
if(!match) break;
int i;
BigNum r=b;
for(i=2;i<=10;i++)
{
BigNum p;
p.s[p.len-1]=i;
BigNum u=b*p;
if(zjbreak;
r=u;
}
i--;
zj=zj-r;
BigNum q;
if(zj==q) zj.len--;
tmp=zj.Nizhi();
}
if(zj.len==1)
{
zj.Clear();
}
return zj;
}
void operator%=(BigNum &a,BigNum b)
{
a=a%b;
}
//////////////////////////////////////////////////赋值///////////////////
void BigNum::operator=(int a)
{
Clear();
if(a<0)
{
s[0]=-1;
a=-a;
}
len=1;
while(a)
{
s[len++]=a%10;
a/=10;
}
}
void BigNum::operator=(const char *a)
{
Clear();
if(*a=='-')
{
s[0]=-1;
a++;
}
len=1;
while(*a&&*a=='0') a++;
while(*a)
{
s[len++]=*a-'0';
a++;
}
if(len==1) len=2;
*this=Nizhi();
}
BigNum BigNum::operator--() // --a;
{
BigNum tmp;
tmp=-1;
*this+=tmp;
return *this;
}
BigNum BigNum::operator--(int) // a--;
{
BigNum ans;
ans=*this;
BigNum tmp;
tmp=-1;
*this+=tmp;
return ans;
}
BigNum BigNum::operator++() // ++a;
{
BigNum tmp;
tmp=1;
*this+=tmp;
return *this;
}
BigNum BigNum::operator++(int) // a++;
{
BigNum ans;
ans=*this;
BigNum tmp;
tmp=1;
*this+=tmp;
return ans;
}
示意一下:
int main(){
BigNum mid;
BigNum a;
a.out();cout<100;//没重载bignum和int的运算符
a+=mid;a.out();cout<out();cout<for(int i=1;i<=50;i++){
a*=mid;a.out();cout<
矩阵取数游戏
解析