高精模板
前言
今天遇到了一道非常恶心的区间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 + b
或a += 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\)等函数。