大整数类模板(可读性优化版)

#include <iostream>
#include <string.h>
using namespace std;
#define DIGIT	4
#define DEPTH	10000
#define MAX     1000
typedef int bign_t[MAX+1];

#ifndef ms
#define ms(x , y) (memset(x , y , sizeof(x)))
#endif // memset

#ifndef mcp
#define mcp(x , y) (memcpy(x , y , sizeof(y)))
#endif // memcpy

#define SGN(x) ( (x)>0 ? 1 : ( (x)<0 ? -1 : 0) )
#define ABS(x) ( (x)>0 ? (x) : -(x) )

///*********************************大整数类封装*********************************************** ///
///**********************************使用说明***************************************************///
///                      1. 前 三 个 comp 函 数 和 add、sub 是 必 须 的                        ///
///                      2. +  -  需 要 add 和 sub                                              ///
///                      3. *  需 要 mul                                                        ///
///                      4. /  %  需 要  div                                                    ///
///                      5.length、zeronum、digit是 独 立 的                                    ///
///                      6.convert 需 要 mul                                                    ///
///                      7.排 列 组 合 需 要 第 四 个 comp 和 convert                          ///
///                      8.注 意 使 用 了 宏 定 义 ms 和 mcp ( 如 上 )                       ///
///                      9.注 意 初 始 化 不 能 bign a=x;                                       ///
///                     10.注 意 不 要 bign a;a=1212121212121212112121212121;(自己理解)         ///
///**********************************************************************************************///
///****************************原始代码摘自互联网***********************************************///
///******************** 代 码 可 读 性 优 化  lc思念·落叶***************************************///
///**********************************************************************************************///
///*****************************优 化 说 明*****************************************************///
///                      1. 重 整 代 码 风 格                                                   ///
///                      2. 比 较 运 算 部 分 代 码 重 写                                      ///
///                      3. 缩 减 代 码 量                                                      ///
///                      4. 加 入 注 释                                                         ///
///                      5. 删 除 了 一 部 分 代 码                                            ///
///*********************************************************************************************///
///************************** lc思念·落叶     2014-08-27 **************************************///
///*********************************************************************************************///


///以下三个 comp 函数 必须
int comp(const bign_t a , const bign_t b)
{
	int i;
	if (a[0]!=b[0])
		return a[0]-b[0];
	for (i=a[0] ; i ; i--)
		if (a[i]!=b[i])
			return a[i]-b[i];
	return 0;
}
int comp(const bign_t a , const int b)
{
	int c[12]={1};
	for (c[1]=b ; c[c[0]]>=DEPTH ; c[c[0]+1]=c[c[0]]/DEPTH , c[c[0]]%=DEPTH , c[0]++);
	return comp(a , c);
}
int comp(const bign_t a , const int c , const int d , const bign_t b)
{
	int i , t=0 , x=-DEPTH*2;
	if (b[0]-a[0]<d&&c)
		return 1;
	for (i=b[0] ; i>d ; i--)
    {
		t=t*DEPTH+a[i-d]*c-b[i];
		if (t>0) return 1;
		if (t<x) return 0;
	}
	for (i=d ; i ; i--)
	{
		t=t*DEPTH-b[i];
		if (t>0) return 1;
		if (t<x) return 0;
	}
	return t>0;
}


/// + - / %需要add  * 不需要add
void add(bign_t a , const bign_t b)
{
	int i;
	for (i=1 ; i<=b[0] ; i++)
		if ((a[i]+=b[i])>=DEPTH)
			a[i]-=DEPTH , a[i+1]++;
	if (b[0]>=a[0])
		a[0]=b[0];
	else
		for ( ; a[i]>=DEPTH&&i<a[0] ; a[i]-=DEPTH , i++ , a[i]++);
	a[0]+=(a[a[0]+1]>0);
}
void add(bign_t a , const int b)
{
	int i=1;
	for (a[1]+=b ; a[i]>=DEPTH&&i<a[0] ; a[i+1]+=a[i]/DEPTH , a[i]%=DEPTH , i++);
	for ( ; a[a[0]]>=DEPTH ; a[a[0]+1]=a[a[0]]/DEPTH , a[a[0]]%=DEPTH , a[0]++);
}

/// + - / %需要sub 
void sub(bign_t a , const bign_t b)
{
	int i;
	for (i=1 ; i<=b[0] ; i++)
		if ((a[i]-=b[i])<0)
			a[i+1]-- , a[i]+=DEPTH;
	for ( ; a[i]<0 ; a[i]+=DEPTH , i++ , a[i]--);
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
}
void sub(bign_t a , const int b)
{
	int i=1;
	for (a[1]-=b ; a[i]<0 ; a[i+1]+=(a[i]-DEPTH+1)/DEPTH , a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH , i++);
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
}
void sub(bign_t a , const bign_t b , const int c , const int d)
{
	int i , x=b[0]+d;
	for (i=1+d ; i<=x ; i++)
		if ((a[i]-=b[i-d]*c)<0)
			a[i+1]+=(a[i]-DEPTH+1)/DEPTH , a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH;
	for ( ; a[i]<0 ; a[i+1]+=(a[i]-DEPTH+1)/DEPTH , a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH , i++);
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
}


/// 只有乘法需要 mul
void mul(bign_t c , const bign_t a , const bign_t b)
{
	int i , j;
	ms(c , 0);
	for (c[0]=a[0]+b[0]-1 , i=1 ; i<=a[0] ; i++)
		for (j=1 ; j<=b[0] ; j++)
			if ((c[i+j-1]+=a[i]*b[j])>=DEPTH)
				c[i+j]+=c[i+j-1]/DEPTH , c[i+j-1]%=DEPTH;
	for (c[0]+=(c[c[0]+1]>0) ; !c[c[0]]&&c[0]>1 ; c[0]--);
}
void mul(bign_t a , const int b)
{
	int i;
	for (a[1]*=b , i=2 ; i<=a[0] ; i++)
    {
		a[i]*=b;
		if (a[i-1]>=DEPTH)
			a[i]+=a[i-1]/DEPTH , a[i-1]%=DEPTH;
	}
	for ( ; a[a[0]]>=DEPTH ; a[a[0]+1]=a[a[0]]/DEPTH , a[a[0]]%=DEPTH , a[0]++);
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
}
void mul(bign_t b , const bign_t a , const int c , const int d)
{
	int i;
	ms(b , 0);
	for (b[0]=a[0]+d , i=d+1 ; i<=b[0] ; i++)
		if ((b[i]+=a[i-d]*c)>=DEPTH)
			b[i+1]+=b[i]/DEPTH , b[i]%=DEPTH;
	for ( ; b[b[0]+1] ; b[0]++ , b[b[0]+1]=b[b[0]]/DEPTH , b[b[0]]%=DEPTH);
	for ( ; !b[b[0]]&&b[0]>1 ; b[0]--);
}

///  / %需要div
void div(bign_t c , bign_t a , const bign_t b)
{
	int h , l , m , i;
	ms(c , 0);
	c[0]= (b[0]<a[0]+1) ? (a[0]-b[0]+2) : 1;
	for (i=c[0] ; i ; sub(a , b , c[i]=m , i-1) , i--)
		for (h=DEPTH-1 , l=0 , m=(h+l+1)>>1 ; h>l ; m=(h+l+1)>>1)
			if (comp(b , m , i-1 , a)) h=m-1;
			else l=m;
	for ( ; !c[c[0]]&&c[0]>1 ; c[0]--);
	c[0]= c[0]>1 ? c[0] : 1 ;
}
void div(bign_t a , const int b , int& c)
{
	int i;
	for (c=0 , i=a[0] ; i;c=c*DEPTH+a[i] , a[i]=c/b , c%=b , i--);
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
}


int length(const bign_t a)
{
	int t , ret;
	for (ret=(a[0]-1)*DIGIT , t=a[a[0]] ; t ; t/=10 , ret++);
	return ret>0 ? ret : 1;
}

int digit(const bign_t a , const int b)
{
	int i , ret;
	for (ret=a[(b-1)/DIGIT+1] , i=(b-1)%DIGIT ; i ; ret/=10 , i--);
	return ret%10;
}

int zeronum(const bign_t a)
{
	int ret , t;
	for (ret=0 ; !a[ret+1] ; ret++);
	for (t=a[ret+1] , ret*=DIGIT ; !(t%10) ; t/=10 , ret++);
	return ret;
}



void convert(int* a , const int h , bign_t b)
{
	int i , j , t=1;
	ms(b , 0);
	for (b[0]=b[1]=1 , i=2 ; i<=h ; i++)
		if (a[i])
			for (j=a[i] ; j ; t*=i , j--)
				if (t*i>DEPTH)
					mul(b , t) , t=1;
	mul(b , t);
}


void comp(int* a , const int l , const int h , const int d)
{
	int i , j , t;
	for (i=l ; i<=h ; i++)
		for (t=i , j=2 ; t>1 ; j++)
			while (!(t%j))
				a[j]+=d , t/=j;
}

void combination(bign_t a , int m , int n)
{
	int* t=new int[m+1];
	ms(t , 0);
	comp(t , n+1 , m , 1);
	comp(t , 2 , m-n , -1);
	convert(t , m , a);
	delete []t;
}

void permutation(bign_t a , int m , int n)
{
	int i , t=1;
	ms(a , 0);
	a[0]=a[1]=1;
	for (i=m-n+1 ; i<=m ; t*=i++)
		if (t*i>DEPTH)
			mul(a , t) , t=1;
	mul(a , t);
}



int read(bign_t a , int &sgn , istream& is=cin)
{
	char str[MAX*DIGIT+2] , ch , *buf;
	int i , j;
	ms(a , 0);
	if (!(is>>str)) return 0;
	buf=str , sgn=1;
	if (*buf=='-') sgn=-1 , buf++;
	int L=strlen(buf);
	for (a[0]=L , i=a[0]/2-1 ; i>=0 ; i--)
		swap(buf[i] , buf[a[0]-1-i]);
	for (a[0]=(a[0]+DIGIT-1)/DIGIT , j=L ; j<a[0]*DIGIT ; buf[j++]='0');
	for (i=1 ; i<=a[0] ; i++)
		for (a[i]=0 , j=0 ; j<DIGIT ; j++)
			a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0';
	for ( ; !a[a[0]]&&a[0]>1 ; a[0]--);
	if (a[0]==1&&!a[1]) sgn=0;
	return 1;
}

void write(const bign_t a , ostream& os=cout)
{
	int i , j;
	for (os<<a[i=a[0]] , i-- ; i ; i--)
		for (j=DEPTH/10 ; j ; j/=10)
			os<<a[i]/j%10;
}

struct bign{
	bign_t num;
	int sgn;
public:

inline bign()/// 必要的 生成函数 不能省略
{
    ms(num , 0);
    num[0]=1;
    sgn=0;
}

inline int operator!()/// 应用于布尔运算 不需任何函数
{
    return num[0]==1&&!num[1];
}

inline bign& operator=(const bign& a)///必须的 拷贝复制函数
{
    mcp(num , a.num);
    sgn=a.sgn;
    return *this;
}

inline bign& operator=(const int a)///必须的 拷贝复制函数 需要add
{
    ms(num , 0);
    num[0]=1;
    sgn=SGN(a);
    add(num , sgn*a);
    return *this;
}

inline bign& operator+=(const bign& a)
/// +=函数 需要 add、comp、sub
{
    if(sgn==a.sgn)
        add(num , a.num);
    else if(sgn&&a.sgn)
    {
        int ret=comp(num , a.num);
        if(ret>0)sub(num , a.num);
        else if(ret<0)
        {
            bign_t t;
            mcp(t , num);
            mcp(num , a.num);
            sub(num , t);
            sgn=a.sgn;
        }
        else
            ms(num , 0) , num[0]=1 , sgn=0;
    }
    else if(!sgn)
        mcp(num , a.num) , sgn=a.sgn;
    return *this;
}

inline bign& operator+=(const int a)
///+=函数 需要 add、comp、sub
{
    if(sgn*a>0)add(num , ABS(a));
    else if(sgn&&a)
    {
        int ret=comp(num , ABS(a));
        if(ret>0)sub(num , ABS(a));
        else if(ret<0)
        {
            bign_t t;
            mcp(t , num);
            ms(num , 0);
            num[0]=1;
            add(num , ABS(a));
            sgn=-sgn;
            sub(num , t);
        }
        else
            ms(num , 0) , num[0]=1 , sgn=0;
    }
    else if(!sgn)
        sgn=SGN(a) , add(num , ABS(a));
    return *this;
}

inline bign operator+(const bign& a)
///+函数 需要+=
{
    bign ret;
    mcp(ret.num , num);
    ret.sgn=sgn;
    ret+=a;
    return ret;
}
inline bign operator+(const int a)
///+函数 需要+= (直接复制上面的内容即可)
{
    bign ret;
    mcp(ret.num , num);
    ret.sgn=sgn;
    ret+=a;
    return ret;
}

inline bign& operator-=(const bign& a)
///-=函数 需要 add、comp、sub
{
    if(sgn*a.sgn<0)add(num , a.num);
    else if(sgn&&a.sgn)
    {
        int ret=comp(num , a.num);
        if(ret>0)sub(num , a.num);
        else if(ret<0)
        {
            bign_t t;
        	mcp(t , num);
            mcp(num , a.num);
            sub(num , t);
            sgn=-sgn;
        }
        else
            ms(num , 0) , num[0]=1 , sgn=0;
    }
    else if(!sgn)
        add(num , a.num) , sgn=-a.sgn;
    return *this;
}
inline bign& operator-=(const int a)
///-=函数 需要 add、comp、sub
{
    if(sgn*a<0)add(num , ABS(a));
    else if(sgn&&a)
    {
        int ret=comp(num , ABS(a));
        if(ret>0)sub(num , ABS(a));
        else if(ret<0)
        {
            bign_t t;
            mcp(t , num);
            ms(num , 0);
            num[0]=1;
            add(num , ABS(a));
            sub(num , t);
            sgn=-sgn;
        }
        else ms(num , 0) , num[0]=1 , sgn=0;
    }
    else if(!sgn)
        sgn=-SGN(a) , add(num , ABS(a));
    return *this;
}

inline bign operator-(const bign& a)
///-函数 需要-=
{
    bign ret;
    mcp(ret.num , num);
    ret.sgn=sgn;
    ret-=a;
    return ret;
}
inline bign operator-(const int a)
///-函数 需要-= (复制上边即可)
{
    bign ret;
    mcp(ret.num , num);
    ret.sgn=sgn;
    ret-=a;
    return ret;
}


inline bign& operator*=(const bign& a)
///*= 只需mul
{
    bign_t t;
    mul(t , num , a.num);
    mcp(num , t);
    sgn*=a.sgn;
    return *this;
}
inline bign& operator*=(const int a)
///*= 只需mul
{
    mul(num , ABS(a));
    sgn*=SGN(a);
    return *this;
}
inline bign operator*(const bign& a)
///* 只需mul
{
    bign ret;
    mul(ret.num , num , a.num);
    ret.sgn=sgn*a.sgn;
    return ret;
}
inline bign operator*(const int a)
///*= 只需mul
{
    bign ret;
    mcp(ret.num , num);
    mul(ret.num , ABS(a));
    ret.sgn=sgn*SGN(a);
    return ret;
}


inline bign& operator/=(const bign& a)
/// /= 只需div
{
    bign_t t;
    div(t , num , a.num);
    mcp(num , t);
    sgn=(num[0]==1&&!num[1])?0:sgn*a.sgn;
    return *this;
}

inline bign& operator/=(const int a)
/// /= 只需div
{
    int t;
    div(num , ABS(a) , t);
    sgn=(num[0]==1&&!num[1])?0:sgn*SGN(a);
    return *this;
}

inline bign operator/(const bign& a)
/// / 只需div
{
    bign ret;
    bign_t t;
    mcp(t , num);
    div(ret.num , t , a.num);
    ret.sgn=(ret.num[0]==1&&!ret.num[1])?0:sgn*a.sgn;
    return ret;
}

inline bign operator/(const int a)
/// / 只需div
{
    bign ret;
    int t;
    mcp(ret.num , num);
    div(ret.num , ABS(a) , t);
    ret.sgn=(ret.num[0]==1&&!ret.num[1])?0:sgn*SGN(a);
    return ret;
}

inline bign& operator%=(const bign& a)
/// %= 只需div
{
    bign_t t;
    div(t , num , a.num);
    if (num[0]==1&&!num[1])sgn=0;
    return *this;
}

inline int operator%=(const int a)
/// %= 需div , add
{
    int t;
    div(num , ABS(a) , t);
    ms(num , 0);
    num[0]=1;
    add(num , t);
    return t;
}

inline bign operator%(const bign& a)
/// % 只需div
{
    bign ret;
    bign_t t;
    mcp(ret.num , num);
    div(t , ret.num , a.num);
    ret.sgn=(ret.num[0]==1&&!ret.num[1])?0:sgn;
    return ret;
}

inline int operator%(const int a)
/// % 需要div、add
{
    bign ret;
    int t;
    mcp(ret.num , num);
    div(ret.num , ABS(a) , t);
    ms(ret.num , 0);
    ret.num[0]=1;
    add(ret.num , t);
    return t;
}

/// ++和-- ///
inline bign& operator++(){*this+=1;return *this;}
inline bign& operator--(){*this-=1;return *this;}

///比较运算///
///需要comp///

inline int operator>(const bign& a)
{
    return sgn>0 ?
          (a.sgn>0 ? comp(num , a.num)>0 : 1) :
              (sgn<0 ? ( a.sgn<0 ? comp(num , a.num)<0 : 0) : a.sgn<0 );
}
inline int operator>(const int a)
{
    return sgn>0 ?
          (a>0 ? comp(num , a)>0 : 1) :
              ( sgn<0 ? ( a<0 ? comp(num , -a)<0 : 0) : a<0 );
}


inline int operator>=(const bign& a)
{
    return sgn>0 ?
          (a.sgn>0 ? comp(num , a.num)>=0 : 1) :
              (sgn<0 ? (a.sgn<0?comp(num , a.num)<=0 : 0) : a.sgn<=0);
}
inline int operator>=(const int a)
{
    return sgn>0 ?
          (a>0 ? comp(num , a)>=0 : 1) :
              (sgn<0 ? (a<0?comp(num , -a)<=0 : 0) : a<=0);
}



inline int operator<(const bign& a)
{
    return !((*this)>=a);

}

inline int operator<(const int a)
{
    return !((*this)>=a);
}

inline int operator<=(const bign& a)
{
    return !((*this)>a);
}

inline int operator<=(const int a)
{
    return !((*this)>a);
}

inline int operator==(const bign& a)
{
    return ((*this)>=a)&&((*this)<=a);
}

inline int operator==(const int a)
{
    return ((*this)>=a)&&((*this)<=a);
}

inline int operator!=(const bign& a)
{
    return !((*this)==a);
}
inline int operator!=(const int a)
{
    return !((*this)==a);
}


/// 重载[]表示第i位上的数字(从个位(1)开始)  需要digit函数
inline int operator[](const int a)
{
    return digit(num , a);
}

///重载输入输出函数 需要read、write
friend inline istream& operator>>(istream& is , bign& a)
{
    read(a.num , a.sgn , is);
    return is;
}

friend inline ostream& operator<<(ostream& os , const bign& a)
{
    if(a.sgn<0)os<<'-';
    write(a.num , os);
    return os;
}



///以下函数注意使用方式 a.f(); 不要f(a);///

inline int length(){return ::length(num);}///计算位数

inline int zeronum(){return ::zeronum(num);}///计算尾零数

inline bign C(const int m , const int n){combination(num , m , n);sgn=1;return *this;}
///a=C(m , n);

inline bign P(const int m , const int n){permutation(num , m , n);sgn=1;return *this;}
///a=A(m , n);

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值