zoukankan      html  css  js  c++  java
  • 高精度模板总结

    高精度结构体定义:

    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;
    }
  • 相关阅读:
    延迟满足是一件在优秀的道路上你必须习惯的事情
    你活成了你的职位嘛?
    《自律力——创建持久的行为习惯,成为你想成为的人》读书笔记
    期末大作业
    第7次实践作业
    第6次实践作业
    第5次实践作业
    第4次实践作业
    第3次实践作业
    第2次实践作业
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/5773830.html
Copyright © 2011-2022 走看看