首页 > 其他分享 >高精度

高精度

时间:2024-04-21 18:55:05浏览次数:20  
标签:10 高精度 int Number long back Base

高精度

因为c++没有大数类,最大的类型是 UNSIGNED LONG LONG 数值范围只有 \([0,2^{64}-1]\),没法满足需要,int128似乎不是正统语言中的内容,略。

所以高精度就是解决大数运算的技巧,把数组按位存储,一般从低位到高位。进制无所谓,但是常用10,为了节约复杂度有时会使用压位,即设 \(10^k\) 进制,可以在复杂度优化一个 \((压的位数)\),但是会遇到运算溢出的问题。,一般使用结构体,让代码更简洁。还要重载运算符,也是避免大量函数影响代码美观。

接下来讨论运算:

\(n,m\) 为两个高精数字位数,n为运算符左边的数,m为运算符右边的数

\(p\) 为低精数字,在运算符右边

加: \(O(n+m)\)

减:\(O(n+m)\)

朴素乘: \(O(nm)\) NTT乘:\(O((n+m)\log(n+m))\)

低精乘: \(O(n)\)

低精除:\(O(n)\)

低精取模:\(O(n)\)

以下是基本模板

const int MAXL=2000;
struct Number{
    long long a[MAXL+10];
    Number(){memset(a,0,sizeof a);}
    Number(int x){
        for(int i=1;i<=MAXL;++i){
            a[i] = x%10;
            x /= 10;
        }
    }
    Number operator + (const Number B)const{
        Number C;
        for(int i=1;i<=MAXL;++i){
            C.a[i] += a[i]+B.a[i];
            if(C.a[i]>=10){
                C.a[i+1] += C.a[i]/10;
                C.a[i] %= 10;
            }
        }
        return C;
    }
    Number operator * (const long long x)const{
        Number C;
        for(int i=1;i<=MAXL;++i){
            C.a[i] += a[i]*x;
            if(C.a[i]>=10){
                C.a[i+1] += C.a[i]/10;
                C.a[i] %= 10;
            }
        }
        return C;
    }
    Number operator / (const long long x)const{
        Number C;
       	long long tmp=0;
        for(int i=MAXL;i>=0;--i){
            C.a[i] = (tmp*10+a[i])/x;
            tmp = (tmp*10+a[i])%x;
        }
        return C;
    }
    void print(){
        int i=MAXL;
        while(i>=1&&a[i]==0)--i;//要判边界
        if(i<1)putchar('0');
        for(;i>=1;--i){
			printf("%c",'0'+a[i]);
		}
        putchar('\n');
    }
};

vector + NTT 版本

const int Base=10;
typedef long long ll;
int r[1<<19];
int G=3,Gi=332748118;
void ntt(vector<ll> &a,int s,int INTT){
	for(int i=0;i<s;++i)
		if(i<r[i])
			swap(a[i],a[r[i]]);
	for(int len=2;len<=s;len<<=1){
		ll gn=qpow(INTT==-1?Gi:G,(mod-1)/len,mod);
		int k=len/2;
		for(int i=0;i<s;i+=len){
			ll g=1;
			for(int j=0;j<k;++j,g=g*gn%mod){
				ll tmp=a[i+j+k]*g%mod;
				a[i+j+k]=(a[i+j]-tmp+mod)%mod;
				a[i+j]=(a[i+j]+tmp)%mod;
			}
		}
	}
	if(INTT==-1){
		ll inv=qpow(s,mod-2,mod);
		for(int i=0;i<s;++i)a[i]=a[i]*inv%mod;
	}
}
struct Number{
	vector<ll> a;
	Number(){
		a.clear();
	}
	Number(int n){
		while(n){
			a.emplace_back(n%Base);
			n/=Base;
		}
	}
	void read(){
		string s;
		cin>>s;
		reverse(s.begin(),s.end());
		for(int i=0;i<(int)s.size();i+=1){
			int t=0;
			for(int j=min((int)s.size(),i+1)-1;j>=i;--j)t=t*10+s[j]-'0';
			a.emplace_back(t);
		}
	}
	Number operator + (int b){
		Number C;
		C.a=a;
		C.a[0]+=b;
		for(int i=0;i<(int)a.size();++i){
			if(C.a[i]>=Base){
				if(i+1<(int)a.size())C.a[i+1]+=C.a[i]/Base;
				else C.a.emplace_back(C.a[i]/Base);
				C.a[i]%=Base;
			}else break;
		}
		return C;
	}
	Number operator * (Number b){
		int n=a.size()-1+b.a.size()-1+1;
		int s=1;
		while(s<n)s<<=1;
		for(int i=0;i<s;++i)
			r[i]=(r[i>>1]>>1)|((i&1)*(s>>1));
		vector<ll> A=a,B=b.a;
		A.resize(s);
		B.resize(s);
		ntt(A,s,1);
		ntt(B,s,1);
		for(int i=0;i<s;++i)A[i]=A[i]*B[i]%mod;
		ntt(A,s,-1);
		Number C;
		C.a=A;
		for(int i=0;i<C.a.size()-1;++i){
			if(C.a[i]>=Base){
				C.a[i+1]+=C.a[i]/Base;
				C.a[i]%=Base;
			}
		}
		while(C.a.back()==0)C.a.pop_back();
		return C;
	}
	Number operator / (int b){
		Number C;
		C.a.resize(a.size(),0);
		ll t=0;
		for(int i=a.size()-1;i>=0;--i){
			t=t*Base+a[i];
			C.a[i]=t/b;
			t%=b;
		}
		while(C.a.back()==0)C.a.pop_back();
		return C;
	}
	void print(){
		if(a.size()==0){
			puts("0");
			return;
		}
		printf("%lld",a.back());
		for(int i=a.size()-2;i>=0;--i)printf("%lld",a[i]);
		puts("");
	}
};

标签:10,高精度,int,Number,long,back,Base
From: https://www.cnblogs.com/life-of-a-libertine/p/18149335

相关文章

  • C++U7-1-高精度加减
    学习目标    高精度加法        [高精度加法] #include<bits/stdc++.h>usingnamespacestd;intmain(){stringa;stringb;intc[10089]={0};intd[10089]={0};inte[10089]={0};cin>>a>>b;in......
  • 「主席树维护高精度」 CF464E The Classic Problem
    发现难点在于维护\(dis_u\)(起点\(s\)到\(u\)的最短路)。如果使用暴力高精度,复杂度会乘上一个\(len\)。考虑边权\(2^w\)的特殊性质,如果使用一个二进制串来维护\(dis\),那么加上边权\(2^w\)相当于将二进制下某一段\(1\)置为\(0\),然后再将一个\(0\)置为\(1\)。说白了......
  • P2142 高精度减法
    P2142高精度减法题目高精度减法。输入两个整数\(a,b\)(第二个可能比第一个大)。输出结果(是负数要输出负号)。样例输入21输出1提示\(20\%\)数据\(a,b\)在longlong范围内;\(100\%\)数据\(0<a,b\le10^{10086}\)。思路根据题意,数据最大范围是\(10^{1008......
  • 好用 爱用 高精度
    做过的都知道适用于哪道题罢高精乘低精。inlinevoidAcheron(llx,inta[],int&lena){ intb[N]; memset(b,0,sizeofb); fo(i,0,lena-1) { b[i]+=a[i]*x; b[i+1]+=b[i]/10; b[i]%=10; } while(b[lena]) { b[lena+1]+=b[lena]/10; b[lena]%=10; lena++......
  • C++实现windows高精度微秒级延时(亲测可用)
    C++实现windows高精度微秒级延时(亲测可用)代码如下:#include<iostream>#include<windows.h>//定义一个结构体来保存性能计数器的频率和时间戳structPerformanceCounter{LARGE_INTEGERfrequency;//计数器频率LARGE_INTEGERstart;//开始时间......
  • GIS入门,EPSG:3857介绍,纯JS如何实现简化得Web墨卡托投影的逆变换和高精度Web墨卡托投影
    EPSG:3857坐标系介绍EPSG:3857坐标系,也称为Web墨卡托投影(WebMercatorprojection),是一种用于Web地图的常见投影系统。它是由谷歌地图在2005年引入并广泛采用的。这个投影系统将地球表面的经纬度坐标转换为平面坐标,使得地图在Web上的显示更加方便和流畅。EPSG:3857坐标系使......
  • 高精度算法(加、减、乘、除,使用c++实现)
    一、概念在我们进行计算的过程中,经常会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位,几百位的情况,而我们面对这样的情况下,  和  的数据范围显然是不够使用的了。因此这时,我们就需要引入一个新的算法,叫做高精度算法。高精度算法:它是处理大数字的数......
  • 高精度、低功耗、小封装电压检测芯片 HXWSEMI桦芯微HX61CC2202MR、HX61CC2702MR、HX61
    HX61C系列芯片是使用CMOS技术开发的高精度、低功耗、小封装电压检测芯片。检测电压在小温度漂移的情况下保持极高的精度。客户可选择CMOS输出或OpenDrain输出。■产品特点高精度:±2%低功耗:2.0µA(Vin=1.5V)检测电压范围:1.0V~6.0V,100mV步进工作电压范围:0.7V......
  • 高精度(较难)
    structBigInt{intn,f;//n是位数,f=1是正数,f=-1是负数inta[N];BigInt():n(0),f(1){}BigInt(intx){n=0,f=(x<0?-1:1);x=f*x;while(x!=0)a[n++]=x%10,x/=10;......
  • 高精度算法
    高精度通常,大整数的存储采用数组的形式,其中数组的首位存储大整数的最低位,末位存储最高位举例来说,对于整数123456789,我们可以使用数组存储如下:makefileCopycodeindex:012345678array:[9,8,7,6,5,4,3,2,1]这样,数组的第一......