高精模板

前言

今天遇到了一道非常恶心的区间DP题 【P1005 矩阵取数游戏】。

本身是一道很简单的区间DP问题。但是数据范围:

\(60\%\) 的数据满足:\(1\le n,m\le 30\),答案不超过 \(10^{16}\)

\(100\%\) 的数据满足:\(1\le n,m\le 80\)\(0\le a_{i,j}\le1000\)

对于剩下\(40\%\)的数据,需要使用高精。

由于懒得次次都手写高精,于是有此模板。

这篇博客,理论上是会随着学习的深入更新的!

模板

高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。

这里使用了压位高精。(既然写了高精就要让他做到最好!)

经极其不完全统计,压位高精取\(10^7\)进制时较快。

总模板(直接复制这里)

const int bse = 1e7;
struct haa{
	ll a[105];int len;
	haa(){len = 1, memset(a,0,sizeof(a));}
	haa(int x){
        memset(a,0,sizeof(a));len = 1;
        while(x){a[len++] = x % bse,x /= bse;}len --;
    }
	void print(){
        printf("%lld",a[len]);
        for(int i = len-1 ; i ; i --)printf("%07lld",a[i]);
    }
}; 
haa operator + (haa& a,haa& b){
	haa ret = 0; ret.len = max(a.len,b.len) + 1;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i] += a.a[i] + b.a[i],
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
haa operator * (haa& a,haa& b){
	haa ret = 0; ret.len = a.len + b.len + 1;
	for(int i = 1 ; i <= a.len ; i ++)
		for(int j = 1 ; j <= b.len ; j ++)
			ret.a[i+j-1] += a.a[i] * b.a[j],
			ret.a[i+j] += ret.a[i+j-1] / bse,
			ret.a[i+j-1] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse ,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
haa operator * (haa& a,int b){
	haa ret = 0 ; ret.len = a.len;
	int x = b;
	while(x) ret.len ++ , x /= bse;
	for(int i = 1 ; i <= a.len ; i ++)
		ret.a[i] += a.a[i] * b,
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
inline void operator += (haa& a,haa& b){a = a+b;}
inline void operator *= (haa& a,int b){a = a*b;}
inline void operator *= (haa& a,haa& b){a = a*b;}
bool operator < (const haa& a,const haa& b){
	if(a.len != b.len) return a.len < b.len;
	for(int i = a.len ; i ; i --)
		if(a.a[i] != b.a[i]) return a.a[i] < b.a[i];
	return 0;
}
bool operator == (const haa& a,const haa& b){
	if(a.len != b.len) return 0;
	for(int i = a.len ; i ; i --)
		if(a.a[i] != b.a[i]) return 0;
	return 1;
}
bool operator > (const haa& a,const haa& b){return !(a<b) && !(a == b);}

以下具体说明。

声明部分(内含构造函数及输出)

const int bse = 1e7;//若需修改进制,修改此处即可
struct haa{
	ll a[105];int len;
	haa(){len = 1, memset(a,0,sizeof(a));}
	haa(int x){
        memset(a,0,sizeof(a));len = 1;
        while(x){a[len++] = x % bse,x /= bse;}len --;
    }
	void print(){
        printf("%lld",a[len]);
        for(int i = len-1 ; i ; i --)printf("%07lld",a[i]);
    }
};

此时,向高精赋值可以写作:

int x = /*...*/;
haa a = x;

或者可以写作:haa a = read();

输出某值可以直接写成:

haa a = /*...*/;
a.print();

高精\(+\)高精

haa operator + (haa& a,haa& b){
	haa ret = 0; ret.len = max(a.len,b.len) + 1;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i] += a.a[i] + b.a[i],
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
inline void operator += (haa& a,haa& b){a = a+b;}

调用时,写作a = a + ba += b

高精\(\times\)低精

haa operator * (haa& a,int b){
	haa ret = 0 ; ret.len = a.len;
	int x = b;
	while(x) ret.len ++ , x /= bse;
	for(int i = 1 ; i <= a.len ; i ++)
		ret.a[i] += a.a[i] * b,
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
inline void operator *= (haa& a,int b){a = a*b;}

调用同上。

高精\(\times\)高精

haa operator * (haa& a,haa& b){
	haa ret = 0; ret.len = a.len + b.len + 1;
	for(int i = 1 ; i <= a.len ; i ++)
		for(int j = 1 ; j <= b.len ; j ++)
			ret.a[i+j-1] += a.a[i] * b.a[j],
			ret.a[i+j] += ret.a[i+j-1] / bse,
			ret.a[i+j-1] %= bse;
	for(int i = 1 ; i <= ret.len ; i ++)
		ret.a[i+1] += ret.a[i] / bse ,
		ret.a[i] %= bse;
	while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
	return ret;
}
inline void operator *= (haa& a,haa& b){a = a*b;}

调用同上。

判断符

bool operator < (const haa& a,const haa& b){
	if(a.len != b.len) return a.len < b.len;
	for(int i = a.len ; i ; i --)
		if(a.a[i] != b.a[i]) return a.a[i] < b.a[i];
	return 0;
}
bool operator == (const haa& a,const haa& b){
	if(a.len != b.len) return 0;
	for(int i = a.len ; i ; i --)
		if(a.a[i] != b.a[i]) return 0;
	return 1;
}
bool operator > (const haa& a,const haa& b){return !(a<b) && !(a == b);}

调用同其他。

可以直接使用\(\max\)\(\min\)等函数。

posted @ 2021-09-09 15:11  Last-Order  阅读(857)  评论(0编辑  收藏  举报