高精度——壓位的思想及應用
阿新 • • 發佈:2018-01-01
是我 c const memset name mes res -- 希望 string 的範圍),然後照樣加減,最後並不影響答案,但是要註意輸出。對於除法,我們此時發現枚舉\(10^4\)到\(10^8\)太慢了,註意到單調性,於是我們考慮二分試商,這樣就也可以在\(log_2 BASE\)的時間之內求出來了。
註意初始化、賦值和輸出。
本文作者frankchenfu,blogs網址http://www.cnblogs.com/frankchenfu/,轉載請保留此文字。
這裏我們簡單介紹一下高精度的計算。
我們都知道在Cpp/C/Pas
等語言中,整數最大能儲存\(2^{64} -1\),超過這個範圍就表示不了了(不包括個別支持int128
的編譯器)。這個時候,我們如果希望把這些整數存儲下來,就需要用到高精度的算法和思想。高精度就是像小學學過的豎式運算一樣的(除法除外)。然後就直接模擬即可。除法一位一位地試商即可。
接下來我們發現就是一位一位地加減很慢,我們考慮如何把它加快速度(減小常數)。如果你有學習過關於bitset
的相關知識,那你肯定對壓位的方法不陌生。我們把十進制位中的每4~8位並在一起(筆者一般壓4位,因為乘法時不會超過int
註意初始化、賦值和輸出。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; typedef int ll; struct bign//big number { //init static const int BASE=(int)1e4,POW=4; static const int MAXLEN=20010; ll num[MAXLEN];//num[0]=length of the big number bign(int tp=0) { memset(num,tp,sizeof(num)); } void clear() { memset(num,0,sizeof(num)); } bool operator=(const char ch[]) { int len=strlen(ch); for(int i=0;i<len;i++) num[(len-i-1)/POW+1]=num[(len-i-1)/POW+1]*10+ch[i]-‘0‘; num[0]=(len-1)/POW+1; } //compare //big number bool operator<(const bign &rsh)const { if(num[0]!=rsh.num[0]) return num[0]<rsh.num[0]; for(int i=num[0];i;i--) { if(num[i]!=rsh.num[i]) return num[i]<rsh.num[i]; } return 0; } //int/long long ll max(ll _x,ll _y) { return _x>_y?_x:_y; } ll min(ll _x,ll _y) { return _x<_y?_x:_y; } //operator //add void operator+=(const bign &rsh) { num[0]=max(num[0],rsh.num[0]); for(int i=1;i<=num[0];i++) { num[i]+=rsh.num[i]; num[i+1]+=num[i]/BASE; num[i]%=BASE; } while(num[num[0]+1]>0) num[0]++; } bign operator+(const bign &rsh)const { bign res=*this;res+=rsh; return res; } //subtract void operator-=(const bign &rsh) { for(int i=1;i<=num[0];i++) { num[i]-=rsh.num[i]; while(num[i]<0) { num[i]+=BASE; num[i+1]--; } } while(num[num[0]]<=0&&num[0]>0) num[0]--; } bign operator-(const bign &rsh)const { bign res=*this;res-=rsh; return res; } //multiply bign operator*(const bign &rsh)const { bign res; res.num[0]=num[0]+rsh.num[0]-1; for(int i=1;i<=num[0];i++) for(int j=1;j<=rsh.num[0];++j) res.num[i+j-1]+=num[i]*rsh.num[j]; for(int i=1;i<=res.num[0];i++) { res.num[i+1]+=res.num[i]/BASE; res.num[i]%=BASE; } while(res.num[res.num[0]+1]>0) { res.num[0]++; res.num[res.num[0]+1]+=res.num[res.num[0]]/BASE; res.num[res.num[0]]%=BASE; } return res; } void operator*=(const bign &rsh) { bign res=*this;res=res*rsh; *this=res; } //divide void operator/=(const ll &rsh) { for(int i=num[0];i>1;i--) { num[i-1]+=(num[i]%rsh*BASE); num[i]/=rsh; } num[1]/=rsh; while(num[0]>0&&num[num[0]]<=0) num[0]--; } bign operator/(const ll &rsh)const { bign temp=*this ; temp/=rsh; return temp; } void operator/=(const bign &rsh) { bign l,r=*this,tmp_one;tmp_one="1"; l.num[0]=1; while(l<r) { bign mid=(l+r+tmp_one)/2; if(*this<(rsh*mid)) r=mid-tmp_one; else l=mid; } *this=l; } bign operator/(const bign &rsh)const { bign res=*this;res/=rsh; return res; } //mod void operator%=(const bign &rsh) { bign res=*this; res=res-res/rsh*rsh; *this=res; } bign operator%(const bign &rsh)const { bign res=*this;res%=rsh; return res; } }; ostream&operator<<(ostream &out,const bign &x) { printf("%d",x.num[x.num[0]]); for(int i=x.num[0]-1;i;i--) printf("%04d",x.num[i]); return out; }
高精度——壓位的思想及應用