高精度模板总结

高精度结构体定义:

struct numlist
{
    static const short L = 85;//做乘法FFT,要开到最大乘数长度的4倍
    char a[L];
    short len;
    void ini(string s)//字符串输入
    {
        fill(a, a + L, 0);
        for (int i = s.length() - 1; i >= 0; i--)
            a[s.length() - i - 1] = s[i] - '0';
        len = s.length();
        if(s[0]=='0')
            len=0;
    }
    void ini(long long int num)//数字输入
    {
        fill(a, a + L, 0);
        len = 0;
        while (num)
        {
            a[len++] = num % 10;
            num /= 10;
        }
    }
    void updateBit()//更新位数,约定0的位数是0
    {
        len = 0;
        for (int i = 0; i<L; i++)
        {
            if (a[i] != 0)
                len = i + 1;
            if (a[i] >= 10)
            {
                int temp = a[i] / 10;
                a[i] %= 10;
                a[i + 1] += temp;
            }
            if (a[i]<0)
            {
                int temp = -(a[i] % 10 != 0) + a[i] / 10;
                a[i] %= 10;
                if (a[i]<0) a[i] += 10;
                a[i + 1] += temp;
            }
        }
    }
    void print()//测试输出
    {
        if (len == 0)
        {
            cout << 0 << endl;
            //puts("0");
            return;
        }
        for (int i = len - 1; i >= 0; i--)
            cout << (int)a[i];
        cout << endl;

        /*
        for(int i=len-1;i>=0;i--)
        printf("%d",a[i]);
        printf("
");
        */
    }
};

大小比较

int BitCmp(numlist a,numlist b)//1:a>b,-1:a<b,0:a==b
{
    if(a.len!=b.len)
        return a.len>b.len?1:-1;
    for(int i=a.len-1;i>=0;i--)
        if(a.a[i]!=b.a[i])
            return a.a[i]>b.a[i]?1:-1;
    return 0;
}

高精度加减

1、高精度加单精度

numlist Badd(numlist a,long long int num)
{
    long long int p=0;
    while(num)
    {
        a.a[p++]+=num%10;
        num/=10;
    }
    a.updateBit();
    return a;
}

2、高精度加高精度(后者可以成倍加入前者,也可以变形实现高精度乘单精度)

numlist Badd(numlist a,numlist b,int f)
{
    int mx=a.len;
    if(b.len>mx) mx=b.len;
    for(int i=0;i<mx;i++)
        a.a[i]+=b.a[i]*f;
    a.updateBit();
    return a;
}

高精度取余

1、高精度取单精度

int mod(numlist a,int b)//高精度取余单精度 输出余数
{
    int temp=0;
    for(int i=a.len-1; i>=0; i--)
        temp=(temp*10+a.a[i])%b;
    return temp;
}

高精度除法

1、高精度除单精度

numlist div(numlist a,int b)
{
    for(int i=a.len-1;i>=0;i--)
    {
        int temp=a.a[i]%b;
        a.a[i]/=b;
        if(i!=0)
            a.a[i-1]+=temp*10;
    }
    a.updateBit();
    return a;
}

高精度乘法

1、高精度乘高精度

numlist Bmut(numlist a,numlist b)
{
    numlist c;
    c.ini(0);
    for(int i=0; i<a.len; i++)
        for(int j=0; j<b.len; j++)
            c.a[i+j]+=a.a[i]*b.a[j];
    c.updateBit();
    return c;
}

2、高精度乘法FFT优化

struct numlist
{
    static const int L = 55000*4;//做乘法FFT,要开到最大乘数长度的4倍
    int a[L];
    int len;
    void ini(string s)//字符串输入
    {
        fill(a, a + L, 0);
        for (int i = s.length() - 1; i >= 0; i--)
            a[s.length() - i - 1] = s[i] - '0';
        len = s.length();
    }
    void ini(long long int num)//数字输入
    {
        fill(a, a + L, 0);
        len = 0;
        if (num == 0) len++;
        while (num)
        {
            a[len++] = num % 10;
            num /= 10;
        }
    }
    void updateBit()//更新位数,约定0的位数是0
    {
        len = 0;
        for (int i = 0; i<L; i++)
        {
            if (a[i] != 0)
                len = i + 1;
            if (a[i] >= 10)
            {
                int temp = a[i] / 10;
                a[i] %= 10;
                a[i + 1] += temp;
            }
            if (a[i]<0)
            {
                int temp = -(a[i] % 10 != 0) + a[i] / 10;
                a[i] %= 10;
                if (a[i]<0) a[i] += 10;
                a[i + 1] += temp;
            }
        }
    }
    void print()//测试输出
    {
        if (len == 0)
        {
            cout << 0 << endl;
            //puts("0");
            return;
        }
        for (int i = len - 1; i >= 0; i--)
            cout << a[i];
        cout << endl;

        /*
        for(int i=len-1;i>=0;i--)
        printf("%d",a[i]);
        printf("
");
        */
    }
};
struct Complex // 复数
{
    double r, i;
    Complex(double _r = 0, double _i = 0) :r(_r), i(_i) {}
    Complex operator +(const Complex &b) {
        return Complex(r + b.r, i + b.i);
    }
    Complex operator -(const Complex &b) {
        return Complex(r - b.r, i - b.i);
    }
    Complex operator *(const Complex &b) {
        return Complex(r*b.r - i*b.i, r*b.i + i*b.r);
    }
};
void change(Complex y[], int len) // 二进制平摊反转置换 O(logn)  
{
    int i, j, k;
    for (i = 1, j = len / 2; i < len - 1; i++)
    {
        if (i < j)swap(y[i], y[j]);
        k = len / 2;
        while (j >= k)
        {
            j -= k;
            k /= 2;
        }
        if (j < k)j += k;
    }
}
void fft(Complex y[], int len, int on) //FFT:on=1; IFFT:on=-1
{
    change(y, len);
    for (int h = 2; h <= len; h <<= 1)
    {
        Complex wn(cos(-on * 2 * PI / h), sin(-on * 2 * PI / h));
        for (int j = 0; j < len; j += h)
        {
            Complex w(1, 0);
            for (int k = j; k < j + h / 2; k++)
            {
                Complex u = y[k];
                Complex t = w*y[k + h / 2];
                y[k] = u + t;
                y[k + h / 2] = u - t;
                w = w*wn;
            }
        }
    }
    if (on == -1)
        for (int i = 0; i < len; i++)
            y[i].r /= len;
}
const LL N = 55000 * 4;
Complex n1[N], n2[N];
int ans[N];
numlist Bmut(numlist &a, numlist &b)
{
    int len1 = a.len, len2 = b.len;
    int len = 1;
    while (len < len1 + len2 + 3)len <<= 1;
    for (int i = 0; i < len; i++)
        n1[i] = Complex(0, 0), n2[i] = Complex(0, 0);
    for (int i = len1 - 1; i >= 0; i--)
        n1[i] = Complex(a.a[i], 0);
    for (int i = len2 - 1; i >= 0; i--)
        n2[i] = Complex(b.a[i], 0);
    fft(n1, len, 1);
    fft(n2, len, 1);
    for (int i = 0; i<len; i++)
        n2[i] = n2[i] * n1[i];
    fft(n2, len, -1);
    numlist c;
    c.ini(0);
    for (int i = 0; i < len; i++)
    {
        c.a[i] += (int)(n2[i].r + 0.005);
        c.a[i + 1] += c.a[i] / 10;
        c.a[i] %= 10;
        if (c.a[i] != 0)c.len = i + 1;
    }
    //c.updateBit();
    return c;
}

高精度快速幂

numlist fastMi(numlist a,int b)
{
    numlist mut;
    mut.ini(1);
    while(b)
    {
        if(b%2!=0)
            mut=Bmut(mut,a);
        a=Bmut(a,a);
        b/=2;
    }
    return mut;
}

 高精度开方

1、模拟手算

numlist Bsqrt(numlist a)
{
    numlist rec,num100,high,preBit;
    num100.ini(100);
    string ans="";//顺序记录每一位
    int pos=a.len-(!(a.len%2)+1);
    numlist temp;
    int initNum=0;
    for(int i=a.len-1;i>=pos;i--)
        initNum*=10,initNum+=a.a[i];
    ans+=sqrt(initNum)+'0';
    preBit.ini(ans);
    initNum-=(int)sqrt(initNum)*(int)sqrt(initNum);
    temp.ini(initNum);//部分余数
    pos-=2;
    for(;pos>=0;pos-=2)
    {
        ans+='0';
        for(int i=preBit.len;i>0;i--)
            preBit.a[i]=preBit.a[i-1];
        preBit.a[0]=0;
        preBit.len++;

        high=preBit;
        high=Add(high,high,1);
        temp=Bmut(temp,num100);
        temp=Add(temp,a.a[pos]+a.a[pos+1]*10);
        numlist pn,pn1;
        numlist pnow,ppre;
        int p=5;
        do
        {
            pn.ini(p),pn1.ini(p-1);
            pnow=Bmut(Add(high,p),pn);
            ppre=Bmut(Add(high,p-1),pn1);
            if(BitCmp(temp,ppre)<0)
                p--;
            else if(BitCmp(pnow,temp)<=0)
                p++;
            else
                break;
        }while(1);
        p--;
        preBit.a[0]=p;
        pn.ini(p);
        pnow=Bmut(Add(high,p),pn);
        temp=Add(temp,pnow,-1);
        ans[ans.length()-1]=p+'0';
    }
    rec.ini(ans);
    return rec;
}
原文地址:https://www.cnblogs.com/LukeStepByStep/p/5773830.html