zoukankan      html  css  js  c++  java
  • 高精度模板(带符号的加减乘除开方/压位)

    最近bzoj挂了几天了,颓得慌。。。

    想想很多基础的算法什么的都没有写过

    (我会说我没写过一次快排吗。。。。。。。

    这些基础的这几天我要完成它们QAQ不然跪了就不爽。。

    注意在赋值一个数的时候一定要先清空!!!!!

    高精模板。。我调了2天啊。。。终于调出来了,不长。80行左右吧。。

    很多细节的。(我用a[0]作为位数和a[N]作为符号)

    在处理bigint的位时,我们最好写个fix来更新位(不然可以造数据让你挂掉。。)

    然后处理符号的话,乘除还好,加减就有些麻烦,我们可以分类讨论下:

    首先是减法(a-b):

    如果a和b都是负号的,那么就相当于b-|a|(这里a是负号),那么我们将a和b的符号位去掉,然后重新调用minus(b, a)即可

    否则如果b是负号,那么相当于a+|b|(b是负号),然后我们将b的符号去掉后调用plus(a, b)即可

    否则如果a是负号,那么相当于-b-|a|(b是正号),那么我们将b的符号标成负后,负数部分就相当于加了,所以调用plus(a, b)即可

    否则a比b小,那么答案就相当于-(b-a),所以我们调换一下做个标记

    加法(a+b):

    首先如果a和b是异号,那么如果是a是负的,将a的标记去掉后调用minus(b, a);如果b是负的,将b的标记去掉后调用minus(a, b)

    否则答案的符号和a的符号相同

    乘法(a×b):

    答案的符号=a的符号^b的符号 && 答案不为0

    除法(a/b):

    同乘法的符号处理。我的除法是用减的方法做的。

    开方:

    直接二分然后验证即可,最好用左闭右开,如果左闭右闭会多一个减法操作。。sad

    ps:做乘法的话如果像我一样是先做乘法后做加法,那么一定要考虑算术溢出。。你懂的。。。

    ps:清空那里不要动不动清空整个数组啊啊啊啊啊sad

    高精度(不压位):

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,(a),sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
     
    const int N=100005;
    int f[11][N+5], tp1[N+5], tp2[N+5], tp3[N+5], tp4[N+5], Ten[N+5], One[N+5], Two[N+5];
    char s[N+5];
    void Plus(int *a, int *b, int *c);
    void Print(int *a);
    inline void fix1(int *a, int len) { while(len>1 && !a[len]) --len; a[0]=len; }
    inline void fix2(int *a, int *b, int *c) { c[N]=(a[N]^b[N])&&(!(c[0]==1 && c[1]==0)); }
    inline void upd(int *a) { memset(a, 0, sizeof(int)*(a[0]+1)); a[0]=1; }
    inline void Init() { Ten[0]=2; Ten[2]=1; One[0]=One[1]=1; Two[0]=1; Two[1]=2; }
    bool cmp(int *a, int *b) {
    	if(a[N]^b[N]) return a[N];
    	if(a[N]==1) swap(a, b);
    	if(a[0]<b[0]) return 1; else if(a[0]>b[0]) return 0;
    	for3(i, a[0], 1) if(a[i]<b[i]) return 1; else if(a[i]>b[i]) return 0;
    	return 0;
    }
    void Minus(int *a, int *b, int *c) {
    	int i, flag=0;
    	if(a[N] && b[N]) { b[N]=a[N]=0; Minus(b, a, c); b[N]=a[N]=1; return; }
    	if(b[N]) { b[N]=0; Plus(a, b, c); b[N]=1; return; }
    	if(a[N]) { b[N]=1; Plus(a, b, c); b[N]=0; return; }
    	if(cmp(a, b)) flag=1, swap(a, b);
    	upd(c);
    	for(i=1; i<=a[0]; ++i) {
    		c[i]+=a[i]-b[i];
    		while(c[i]<0) c[i]+=10, c[i+1]-=1;
    	}
    	fix1(c, i); if(flag) c[N]=1;
    }
    void Plus(int *a, int *b, int *c) {
    	if(a[N]^b[N]) { if(a[N]) { a[N]=0; Minus(b, a, c); a[N]=1; } else { b[N]=0; Minus(a, b, c); b[N]=1; } return; }
    	upd(c);
    	int k=0, len=max(a[0], b[0]), i;
    	for(i=1; i<=len || k; ++i) {
    		c[i]=a[i]+b[i]+k;
    		k=c[i]/10; if(c[i]>=10) c[i]%=10;
    	}
    	fix1(c, i); c[N]=a[N];
    }
    void Multi(int *a, int *b, int *c) {
    	upd(c);
    	for1(i, 1, a[0]) for1(j, 1, b[0]) c[i+j-1]+=a[i]*b[j];
    	int k=0, i, len=a[0]+b[0]-1;
    	for(i=1; i<=len || k; ++i) {
    		c[i]+=k;
    		k=c[i]/10; if(c[i]>=10) c[i]%=10;
    	}
    	fix1(c, i); fix2(a, b, c);
    }
    void Div(int *a, int *b, int *c) {
    	upd(c); upd(tp1); upd(tp2); upd(tp3);
    	int i, *t=tp1, *ans=tp2, *k=tp3, flag=b[N]; b[N]=0;
    	for(i=a[0]; i>=1; --i) {
    		Multi(k, Ten, t); swap(k, t);
    		k[1]=a[i];
    		Multi(ans, Ten, t); swap(ans, t);
    		while(!cmp(k, b)) {
    			Plus(ans, One, t); swap(ans, t);
    			Minus(k, b, t); swap(k, t);
    		}
    	}
    	memcpy(c, ans, sizeof(int)*(ans[0]+1));
    	b[N]=flag;
    	fix1(c, a[0]); fix2(a, b, c);
    }
    void Print(int *a) {
    	if(a[N]) printf("-");
    	for3(i, a[0], 1) print(a[i]);
    	puts("");
    }
    void stoi(char *x, int *a) {
    	int len=strlen(s), i=0;
    	if(x[0]=='-') a[N]=1, ++i; a[0]=len-i;
    	for(; i<len; ++i) a[len-i]=s[i]-'0';
    }
    void sqrt(int *a, int *c) {
    	upd(c);
    	int *l=f[3], *r=f[4], *m=f[5], *t=f[6];
    	l[0]=1; r[a[0]+1]=1; r[0]=a[0]+1;
    	while(cmp(l, r)) {
    		upd(t); upd(m); 
    		Plus(l, r, t); 
    		Div(t, Two, m);
    		Multi(m, m, t);
    		if(!cmp(a, t)) { swap(l, m); Plus(l, One, t); swap(l, t); }
    		else swap(r, m);
    	}
    	Minus(l, One, t); swap(l, t);
    	memcpy(c, l, sizeof(int)*(N+5));
    }
    int main() {
    	Init();
    	scanf("%s", s); stoi(s, f[1]);
    	sqrt(f[1], f[2]);
    	Print(f[2]);
    	return 0;
    }
    

    压位的除法有点难处理,,我还写不出来QAQ

    等有什么快速的办法再写吧。。

    压位(7位,因为我是先乘后进位),加减乘带符号

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,(a),sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=100005;
    int f[11][N+5], tp1[N+5], tp2[N+5], tp3[N+5], Ten[N+5], One[N+5];
    char s[N+5];
    void Plus(int *a, int *b, int *c);
    void Print(int *a);
    inline void fix1(int *a, int len) { while(len>1 && !a[len]) --len; a[0]=len; }
    inline void fix2(int *a, int *b, int *c) { c[N]=(a[N]^b[N])&&(!(c[0]==1 && c[1]==0)); }
    inline void upd(int *a) { memset(a, 0, sizeof(int)*(a[0]+1)); a[0]=1; }
    inline void Init() { Ten[0]=2; Ten[2]=1; One[0]=One[1]=1; }
    bool cmp(int *a, int *b) {
    	if(a[N]^b[N]) return a[N];
    	if(a[N]==1) swap(a, b);
    	if(a[0]<b[0]) return 1; else if(a[0]>b[0]) return 0;
    	for3(i, a[0], 1) if(a[i]<b[i]) return 1; else if(a[i]>b[i]) return 0;
    	return 0;
    }
    void Minus(int *a, int *b, int *c) {
    	int i, flag=0;
    	if(a[N] && b[N]) { b[N]=a[N]=0; Minus(b, a, c); b[N]=a[N]=1; return; }
    	if(b[N]) { b[N]=0; Plus(a, b, c); b[N]=1; return; }
    	if(a[N]) { b[N]=1; Plus(a, b, c); b[N]=0; return; }
    	if(cmp(a, b)) flag=1, swap(a, b);
    	upd(c);
    	for(i=1; i<=a[0]; ++i) {
    		c[i]+=a[i]-b[i];
    		while(c[i]<0) c[i]+=10, c[i+1]-=1;
    	}
    	fix1(c, i);
    	if(flag) c[N]=1;
    }
    void Plus(int *a, int *b, int *c) {
    	if(a[N]^b[N]) { if(a[N]) { a[N]=0; Minus(b, a, c); a[N]=1; } else { b[N]=0; Minus(a, b, c); b[N]=1; } return; }
    	upd(c);
    	int k=0, len=max(a[0], b[0]), i;
    	for(i=1; i<=len || k; ++i) {
    		c[i]=a[i]+b[i]+k;
    		k=c[i]/10; if(c[i]>=10) c[i]%=10;
    	}
    	fix1(c, i); fix2(a, b, c);
    }
    void Multi(int *a, int *b, int *c) {
    	upd(c);
    	for1(i, 1, a[0]) for1(j, 1, b[0]) c[i+j-1]+=a[i]*b[j];
    	int k=0, i, len=a[0]+b[0]-1;
    	for(i=1; i<=len || k; ++i) {
    		c[i]+=k;
    		k=c[i]/10; if(c[i]>=10) c[i]%=10;
    	}
    	fix1(c, i); fix2(a, b, c);
    }
    void Div(int *a, int *b, int *c) {
    	upd(c); upd(tp1); upd(tp2); upd(tp3);
    	int i, *t=tp1, *ans=tp2, *k=tp3, flag=b[N]; b[N]=0;
    	for(i=a[0]; i>=1; --i) {
    		Multi(k, Ten, t); swap(k, t);
    		Multi(ans, Ten, t); swap(ans, t);
    		k[1]=a[i];
    		while(!cmp(k, b)) {
    			Plus(ans, One, t); swap(ans, t);
    			Minus(k, b, t); swap(k, t);
    		}
    	}
    	memcpy(c, ans, sizeof(int)*(N+5));
    	b[N]=flag;
    	fix1(c, a[0]); fix2(a, b, c);
    }
    void sqrt(int *a, int *c) {
    	upd(c);
    	int *l=f[3], *r=f[4], *m=f[5], *t=f[6];
    	l[0]=1; r[a[0]+1]=1; r[0]=a[0]+1;
    	while(cmp(l, r)) {
    		upd(t); upd(m); 
    		Plus(l, r, t); 
    		Div(t, Two, m);
    		Multi(m, m, t);
    		if(!cmp(a, t)) { swap(l, m); Plus(l, One, t); swap(l, t); }
    		else swap(r, m);
    	}
    	Minus(l, One, t); swap(l, t);
    	memcpy(c, l, sizeof(int)*(N+5));
    }
    void Print(int *a) {
    	if(a[N]) printf("-");
    	for3(i, a[0], 1) print(a[i]);
    	puts("");
    }
    void stoi(char *x, int *a) {
    	int len=strlen(s), i=0;
    	if(x[0]=='-') a[N]=1, ++i; a[0]=len-i;
    	for(; i<len; ++i) a[len-i]=s[i]-'0';
    }
    int main() {
    	Init();
    	scanf("%s", s); stoi(s, f[1]);
    	scanf("%s", s); stoi(s, f[2]);
    	Plus(f[1], f[2], f[3]); Print(f[3]);
    	Minus(f[1], f[2], f[3]); Print(f[3]);
    	Multi(f[1], f[2], f[3]); Print(f[3]);
    	Div(f[1], f[2], f[3]); Print(f[3]);
    	return 0;
    }
    
  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3991331.html
Copyright © 2011-2022 走看看