【重载运算符+压位】高精度模板

昨天做一道DP的题(矩阵取数游戏),本来是很简单的,但是要用高精度,又不想用__int128水过去(谁让NOIP不让),于是自己打了一个小时,最后挂了。。。

于是本蒟蒻痛定思痛,感觉高精度还是重载运算符好用,就花了几个小时打了一个高精度模板:

/*采用重载运算符,压4位
支持高精数输入与输出、高精加(减)高精、高精乘低(高)精、高精除(模)低精、高精的比较 
注意:暂不支持负数!!!*/
#include<cstdio>
#include<cstring>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=128,base=1e4;//base是压4位的基数 
struct HP{
    private:
    int a[N],len;
    inline void clear(){while(!a[len]&&len>1) --len;}//清除前导0 
    public:
    HP(){ //结构体初始化 
        memset(a,0,sizeof a);len=0;
    }    
    /*以下是高精度的输入与输出*/ 
    void init_i(int x) {//用int初始化高精度数
        stack<char> st;string s;
        while(x){
            st.push(x%10+'0');
            x/=10;
        }
        while(!st.empty()) s+=st.top(),st.pop();//其实就是把int转换为string再调用init_s()
        init_s(s);
    }
    //注意因为是压4位的,所以输入和输出都要特殊处理 
    void init_s(string s){//用string初始化高精度数 
        int l=s.length();
        for(int i=0;i<=l;++i){
            int j=(l-i+3)/4;
            a[j]=(a[j]<<1)+(a[j]<<3)+(s[i]^48);
        }
        len=(l+3)/4;
    } 
    void print(){//输出高精度数 
        printf("%d",a[len]);
        for(int i=len-1;i>0;--i)
            for(int j=base/10;j>0;j/=10) printf("%d",a[i]/j%10);
        puts("");
    }
    /*以下是重载运算符*/ 
    HP operator +(const HP &x){//高精加高精 
        HP res;res.len=max(len,x.len);int k=0;
        for(int i=1;i<=res.len;++i){
            res.a[i]=a[i]+x.a[i]+k;
            k=res.a[i]/base;
            res.a[i]%=base;
        }
        if(k>0) res.a[++res.len]=k;
        return res;
    }
    HP operator -(const HP &x){//高精减高精(注意这里默认被减数大于减数,否则会出错) 
        HP res=*this;//相当于用res拷贝被减数 
        for(int i=1;i<=len;++i){
            res.a[i]-=x.a[i];
            if(res.a[i]<0) --res.a[i+1],res.a[i]+=base;
        }
        res.clear();
        return res;
    }
    HP operator *(const int &x){//高精乘低精 
        HP res=*this;
        for(int i=1;i<=len;++i) res.a[i]*=x;
        for(int i=1;i<=len;++i) res.a[i+1]+=res.a[i]/base,res.a[i]%=base;
        int &end=res.len;
        while(res.a[end+1]>0){++end;res.a[end+1]+=res.a[end]/base,res.a[end]%=base;}
        return res; 
    }
    HP operator *(const HP &x){//高精乘高精 
        HP res;res.len=len+x.len;
        for(int i=1;i<=len;++i)
            for(int j=1;j<=x.len;++j){
                res.a[i+j-1]+=a[i]*x.a[j];
                res.a[i+j]+=res.a[i+j-1]/base;
                res.a[i+j-1]%=base;
            }
        res.clear();
        return res;
    }
    HP operator /(const int &x){//高精除低精 
        HP res;res.len=len;
        int k=0;
        for(int i=len;i>0;--i){
            k=k*base+a[i];
            res.a[i]=k/x;
            k%=x;
        }
        res.clear();
        return res;
    }
    int operator %(const int &x){//高精模低精 
        int k=0;
        for(int i=len;i>0;--i){
            k=k*base+a[i];
            k%=x;
        }
        return k;//其实跟高精除低精差不多的,只不过不用存res,返回的是k 
    }
    bool operator <(const HP &x)const{//重载小于号 (可以仿造重载大于号) 
        if(len==x.len){ 
            int i;
            for(i=len;a[i]==x.a[i]&&i>1;--i);
            if(i>=1) return a[i] < x.a[i];
            else return false;
        }
        else return len < x.len;
    }
};
HP max(HP a,HP b){
    if(a<b) return b;
    return a;
}
HP min(HP a,HP b){
    if(a<b) return a;
    return b;
}
HP a,b,ans;
string sa,sb;
int main()
{
    cin>>sa>>sb;
    a.init_s(sa);b.init_s(sb);
    ans=a*b;
    ans.print();
    return 0; 
}
View Code

注意暂不支持负数,如果发现有bug欢迎指出。

想粘板子就粘吧,打得丑我承认

2018-10-20

猜你喜欢

转载自www.cnblogs.com/gosick/p/9822197.html