计算机很笨,$long long$太短,还动不动就溢出,于是高精度出现了。

变量/常量定义

辅助压位的宏定义
#define pow 4//压位宽度
#define size 10005//位数=(size-1)*pow
#define base 10000//base=10^pow
定义并初始化结构体
struct bign{
    int len,s[size];
    //len代表高精度的位数(压位后),s中保存数值。
    bign(){//和结构体同名的构造函数,用于初始化结构体中的变量。
        len=1; 
        memset(s,0,sizeof(s));
    }//.........
}

赋值运算符

重载=号(将整型/字符串转化为高精)
bign(int b){//构造函数,将一个整型存入高精度
    len=0;
    memset(s,0,sizeof(s));
    do s[++len]=b%base;
    while(b/=base);
}
bign operator =(int b){//重载等号
    return *this=bign(b);
}
bign(const char *b){//构造函数,将一个字符串存入高精度
    int xx=strlen(b);
    len=(xx-1)/pow+1;
    //小技巧 如果一个数位数能被pow整除 len=xx/pow
    //        如果不能则 len=(xx/pow)+1
    //令len=(xx-1)/pow+1能同时满足上述情况,无需讨论
    memset(s,0,sizeof(s));
    for(int i=0,j=len;i<xx;i++){
        if(i&&(xx-i)%pow==0) j--;
        //小技巧 当(xx-i)%pow==0时表明已经到压位后新一位的开始 j--
        //      但如果xx能被pow整除,一开始就是第一位,j就不能减
        s[j]=s[j]*10+b[i]-'0';
    }
}
bign operator =(const char *b){//重载等号
    return *this=bign(b);
}

比较运算符

重载< > ==
bool operator <(const bign &b)const{
    if(len!=b.len) return len<b.len;//位少则数小
    for(int i=len;i;i--){
        if(s[i]!=b.s[i]) return s[i]<b.s[i];
        //位数同 高位小则数小
    }
    return false;
}
bool operator >(const bign &b)const{
    if(len!=b.len) return len>b.len;//位多则树大
    for(int i=len;i;i--){
        if(s[i]!=b.s[i]) return s[i]>b.s[i];
        //位数同 高位大则数大
    }
    return false; 
}
bool operator ==(const bign &b)const{
    return !(*this>b)&&!(*this<b);
    //又不大于又不小于当然就是等于鸭
}

算术运算符

去除前导0
//减/除运算后位数可能减少,就会产生前导0
void clear(){
    while(len>1&&!s[len])len--;
}
重载加法运算
bign operator +(const bign &b){
    bign c;
    c.len=max(len,b.len);
    //一个n位数与一个m位数相加(n>=m)
    //结果可能是n位(不进位)和n+1位(进一位)
    int g=0;
    for(int i=1;i<=c.len;i++){
        c.s[i]=s[i]+b.s[i]+g;//同位相加
        if(c.s[i]>=base){//往后进位
            g=1;c.s[i]-=base;
        }
        else g=0;
    }
    if(g) c.s[++c.len]=1;//进位
    return c;//不要忘了返回!!!
}
重载减法运算
bign operator -(const bign &b){
    bign c;
    c.len=len;
    int g=0;
    for(int i=1;i<=len;i++){
        c.s[i]=s[i]-b.s[i]-g;//同位相减
        if(c.s[i]<0){//往后借位
            g=1;c.s[i]+=base;
        }
        else g=0;
    }
    c.clear();//去除前导0
    return c;//不要忘了返回!!!
}
重载乘法运算
bign operator *(const bign &b){
    bign c;
    c.len=len+b.len;
    for(int i=1;i<=len;i++){//枚举第一个数的每一位
        for(int j=1;j<=b.len;j++){//枚举第二个数的每一位
            c.s[i+j-1]+=s[i]*b.s[j];//它们积的贡献在第(i+j-1)位
            c.s[i+j]+=c.s[i+j-1]/base;//进位
            c.s[i+j-1]%=base;
        }
    }
    return c;//不要忘了返回!!!
}
重载除法运算(高精/低精)
bign operator /(int b){//菜鸡写不来高精除高精QAQ
    bign c;
    c.len=len;
    int g=0;
    for(int i=len;i;i--){//除法要从最高位开始(还好我小学听了数学课)
        g=base*g+s[i];//上一位除完剩下的加上这一位
        c.s[i]=g/b;//记录答案
        g%=b;//记录这次除完剩下的
    }
    c.clear();//除去前导0
    return c;//不要忘了返回!!!
} 

输入输出

背就完了
char s[size*pow];//字符串输入输出该开多大开多大
istream& operator >>(istream &in,bign &c){
    in>>s; c=s; return in;
}
ostream& operator <<(ostream &out,const bign &c){
    out<<c.s[c.len];//先把最高位输出了(不用补全全前面的0)
    for(int i=c.len-1;i;i--){
        out<<setfill('0')<<setw(pow)<<c.s[i];
        //setw(x)表示填充后的位数。
        //setw默认填充的内容为空格,可以setfill()配合使用设置其他字符填充。
        //out<<setfill('0')<<setw(pow)<<c.s[i];
        //表示要填充到pow位,不够的用0来填充。
    }
    return out;
}

撒花★,°:.☆( ̄▽ ̄)/$:.°★