【原创】高精度(压位储存)模板

无聊写了个高精度模板玩玩......


  1 /*
2 高精度(压位储存)
3 */
4 #include <cstdlib>
5 #include <iostream>
6 #include <cstdio>
7 #include <cstring>
8 #include <cmath>
9 const int MAX=10005;//最长长度
10 using namespace std;
11 //高精度结构体,先声明后实现
12 struct hp
13 {
14 //注意,这里用num[0]来保存位数
15 int num[MAX];
16
17 //-------赋值与初始化-------//
18 hp() {}
19 hp & operator =(const char*);//从字符串赋值
20 hp & operator =(int);//从整型赋值
21 hp (int);
22
23 //-------普通运算符-------//
24 hp operator + (const hp &) const;
25 hp operator - (const hp &) const;
26 hp operator * (const hp &) const;
27 hp operator / (const hp &) const;//注意后面两个的实现
28 hp operator % (const hp &) const;
29
30 //-------比较运算符-------//
31 bool operator > (const hp &) const;
32 bool operator < (const hp &) const;
33 bool operator == (const hp &) const;
34 bool operator >= (const hp &) const;
35 bool operator <= (const hp &) const;
36
37 }shu;
38 //-------实现-------//
39 hp & hp::operator =(const char* str)
40 {
41 memset(num,0,sizeof(num));
42 int len=strlen(str),j=1,k=1;
43 for (int i=1;i<=len;i++)//注意从1开始循环
44 {
45 if (k==10000) j++,k=1;
46 num[j]+=k*(str[len-i]-‘0‘);
47 k*=10;
48 }
49 num[0]=j;
50 return *this;
51 }
52 hp & hp::operator =(int a)
53 {
54 char s[MAX];
55 sprintf(s,"%d",a);
56 return *this=s;
57 }
58 hp::hp(int n){*this=n;}
59 hp hp::operator +(const hp & t)const
60 {
61 hp c;
62 memset(c.num,0,sizeof(c.num));
63 c.num[0]=max(num[0],t.num[0]);
64 for (int i=1;i<=c.num[0];i++)
65 {
66 c.num[i]=num[i]+t.num[i];
67 if (c.num[i]>=10000){
68 c.num[i+1]++;
69 c.num[i]-=10000;
70 }
71 }
72 while (c.num[c.num[0]+1]>0) c.num[0]++;
73 return c;
74 }
75 hp hp::operator -(const hp & t)const
76 {
77 hp c;
78 memset(c.num,0,sizeof(c.num));
79 c.num[0]=num[0];
80 for (int i=1;i<=c.num[0];i++)
81 {
82 c.num[i]+=num[i]-t.num[i];
83 if (c.num[i]<0){
84 c.num[i+1]--;
85 c.num[i]+=10000;
86 }
87 }
88 while (c.num[c.num[0]]==0 && c.num[0]>1) c.num[0]--;
89 return c;
90 }
91 hp hp::operator *(const hp & t)const
92 {
93 hp c;
94 memset(c.num,0,sizeof(c.num));
95 c.num[0]=num[0]+t.num[0]+1;//位数
96 for (int i=1;i<=num[0];i++)
97 for (int j=1;j<=t.num[0];j++)
98 {
99 c.num[i+j-1]=num[i]*t.num[j];
100 c.num[i+j]+=c.num[i+j-1]/10000;
101 c.num[i+j]%=10000;
102 }
103 while (c.num[c.num[0]]==0 && c.num[0]>1) c.num[0]--;
104 return c;
105 }
106 bool hp::operator > (const hp &b) const
107 {
108 if (num[0]!=b.num[0]) return num[0]>b.num[0];
109 for (int i=num[0];i>=1;i--)
110 if (num[i]!=b.num[i])
111 return (num[i]>b.num[i]);
112 return false;
113 }
114 bool hp::operator < (const hp &b) const {return b>*this;}
115 bool hp::operator <= (const hp &b) const {return !(*this>b);}
116 bool hp::operator >= (const hp &b) const {return !(b>*this);}
117 bool hp::operator == (const hp &b) const {return !(b>*this)&&!(*this>b);}
118 hp hp::operator /(const hp & b)const//二分除法
119 {
120 hp c, d;
121 c.num[0]=num[0]+b.num[0]+1;
122 d.num[0]=0;//d用来存储余数
123 for (int i=num[0];i>=1;i--)
124 {
125 memmove(d.num+2,d.num+1,sizeof(d.num)-sizeof(int)*2);
126 d.num[0]++;
127 d.num[1]=num[i];
128
129 int left=0,right=9999,mid;
130 while (left<right)
131 {
132 mid =(left+right)/2;
133 if (b*hp(mid)<=d) left=mid+1;
134 else right=mid;
135 }
136 c.num[i]=right-1;
137 d=d-b*hp(right-1);
138 }
139 while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;
140 return c;
141 }

时间: 2024-07-30 20:32:12

【原创】高精度(压位储存)模板的相关文章

高精度——压位的思想及应用

本文作者frankchenfu,blogs网址http://www.cnblogs.com/frankchenfu/,转载请保留此文字. 这里我们简单介绍一下高精度的计算. 我们都知道在Cpp/C/Pas等语言中,整数最大能储存\(2^{64} -1\),超过这个范围就表示不了了(不包括个别支持int128的编译器).这个时候,我们如果希望把这些整数存储下来,就需要用到高精度的算法和思想.高精度就是像小学学过的竖式运算一样的(除法除外).然后就直接模拟即可.除法一位一位地试商即可. 接下来我们发

用到了卡特兰数的性质,还有高精度压位,筛法找素数

一列火车n节车厢,依次编号为1,2,3,-,n. 每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种. 输入格式 输入一个整数n,代表火车的车厢数. 输出格式 输出一个整数s表示n节车厢出栈的可能排列方式数量. 数据范围 1≤n≤60000 输入样例: 3 输出样例: 5 这道题的本质是卡特兰数 卡特兰数介绍(引用math73) 筛法求素数 最重要的是如何求解组合数,压位思想,还有组合数C(2n)(n)这个式子展开以后,用上下同时除以连续的质数的方法,将答案一点一点凑出来,

高精度压位

压位的原因 正常的高精度计算中,每一位只存了一位数字,可是当面对比较大的计算的时候呢,如果说每一位都只存一位数字,那么计算的时间就会比较地长.这个时候可以通过每一位高精度中存储多位数字的方法来降低运算的时间 例题引入 简单的来说就是 一个高精度的开根号,只要求开到整数向下取整就可以了.数据范围是10^1000; 首先就是开高精度根号的方法,很容易想到的方法就是二分或者是手动开根号.我这里使用的是二分的方法. 这一道题最开始我是直接高精度来的,然后TLE了,接着我压了四位,还是TLE了,然后直接1

高精度模板2(带符号压位加减乘除开方封包)

原来的那个模板:http://www.cnblogs.com/iwtwiioi/p/3991331.html 估计已经不用了. 现在我重新封包好了一个,一定很好用QAQ 加减乘除带开方带压位带重载运算符 注意一下符号即可,一定写的时候要手推四种情况!! 然后在重载<的时候,一定要注意同时判断!!!!要不然又错.. struct big { typedef ll INT; static const INT S=100000000; static const int S_n=9; static co

codevs 3119 高精度练习之大整数开根 (各种高精+压位)

/* codevs 3119 高精度练习之大整数开根 (各种高精+压位) 二分答案 然后高精判重 打了一个多小时..... 最后还超时了...压位就好了 测试点#1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms 测试点#3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms 测试点#4.in 结果:AC 内存使用量: 256kB 时间使用量: 10ms 测试点#5.in 结果:AC 内

[SDOI2009]SuperGCD 【压位高精度+辗转相减】

题目链接: https://www.luogu.org/problemnew/show/P2152 题目概述:  计算两个大整数(A,B)的最大公因数 数据范围 0 < A , B ≤ 10 ^ 其一在于辗转相减法--辗转相除法的优化(针对大数,避免了大数的模运算带来的多方面的复杂度) 思想就是 以数次 A-B  代替 A%B (这二者是等价的) 辗转相减法: 1 /* 2 Write(X) 输出X 3 Down(X) X除以2 4 Up(X) X乘以2 5 */ 6 void Solve(){

[BZOJ4942][NOI2017]整数(线段树+压位)

CCF的题经常是对于一个不是非常高级的算法或数据结构挖掘性质进行优化. 松爷的题总是充满常数优化气息,这个题也确实是在常数上做文章. 首先如果全加的话是可以直接暴力的,因为可以证明对每一位来说是均摊$O(1)$的,将a二进制分解一次. 然后将暴力想下去之后容易发现,二进制加法如果进位,肯定是找到这一位之前第一个为0的位加一,然后这两位之间的所有位都变成0(就是模拟竖式加法),减法反之. 于是这个东西就是前驱查找和区间修改,应用线段树解决,$O(n\log^{2}n)$. 但是看到极其相近的数据范

原创:MD5 32位加密软件

网站后台数据库切勿使用明文保存密码,否则一旦黑客拿下你的Webshell,后果不堪设想. 网站后台密码加密大多数采用的就是MD5算法加密.今天给大家送一个本人用c#简单编写的MD5 32位加密程序,虽然没有什么技术含量,但保证没有后门. 程序截图: 开放源码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing;

压位高精

压位高精:即通过将原来数组中一个位置存一位数,改为一个位置存p位数(8-10).本质上是一种利用进制转换思想的压缩方式. 压位高精VS普通高精优势: 1.节省空间.(10倍以上) 2.节省时间(循环次数少)(10倍) 3.在对于高精与低精(乘法不超int)运算时,可以利用进制较高的优势,达到简化代码量的目的.(不需要频繁进位) 例题:洛谷 P3223 组合数学+高精乘低精. #include<cstdio> #include<algorithm> #include<iostr