周教授大数模板【完整版】
2012-12-25 22:05
288 查看
/*这是周尚超教授多年前写的,希望看过此文的能记住有这么一位数学家一直在默默地奉献!! 简单的介绍一下我们教授吧,文革期间自学外语,精通英语,会 日,俄,德,法五种外语,早期的优秀知识分子,一个没有读过大学的青年于 1983年自学考上了武汉大学的研究生,毕业后从事数学事业,在国外多家学术报发表过各种学术文章,在学术上颇有建树,有着国际数学家的荣誉, 带出了一大批的优秀人才,不扯淡了....上次有幸到教授家吃饭,真的很感谢...今天圣诞了,希望教授的身体能够好起来...这辈子能成为教授的学生, 也是一种幸福...*/ /*高精度计算模板函数 2011-9-5 本文件名 bigint.h 整数 大于 2^64-1, 称为大整数,要用高精度计算 例如 a=123444455556666777788889999 是27位数 用数组表示它 ,最低4位用 a[1]=9999表示,称a[1]是10000进制数的 个位数。 a[2]=8888;a[3]=7777,a[4]=6666,a[5]=5555,a[6]=4444,a[7]=123; a[0]=7;表示它是万进制 数的7位数。 Base=10000进制 。 大整数用字符串读入, 再用函数 tran 转为数组 本文件有下列函数 trans,comp,PN,copy,add,sub,mult,mult,Div,Div,gcd 程序中用到高精度计算时, (1)将本文件复制到 int main()的前面, 然后将不需要的函数删除,也可以不删除. (2) 也可以加上 #include<bigint.h> 例如 hdu1002 A + B Problem II,只用到加法,可将sub,mult,mult,Div删除 要用高精度计算的题 hdu1002 A + B Problem II hdu1502 Regular Words hdu1042 n! n<=10000 hdu1133 Buy the Ticket http://acm.hdu.edu.cn/showproblem.php?pid=1133 zju2061 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2061 hdu1134 Game of Connections catalan数 h[1]=1,h =h[n-1]*(4n-2) /(n+1) ,n<=100 hdu1250 Hat's Fibonacci http://acm.hdu.edu.cn/showproblem.php?pid=1250 pku2084 Game of Connections = hdu1134 pku2515 Birthday Cake 计算 1+2^M +...+n^M, n<=10^41, M<=100 pku1220 NUMBER BASE CONVERSION pku2680 Computer Transformation pku3181 Dollar Dayz pku3199 Uncle Jack pku3324 Lucas-Lehmer Test pku3331 The Idiot of the Year Contest */ #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include<stdio.h> #include<string.h> using namespace std; const int Base=10000; //万进制 int 最大,如果只用 +,-,可加大Base=1000000000 int ONE[]={1,1}; //大整数 1 int ZERO[]={1,0}; //大整数 0 int comp(int *a, int *b);//大整数比较大小 int comp(int *a, int *b,int t);//大整数比较大小 void trans(char *ch,int *A); //串->数 base=10000,A[1]是最低位,A[0]是位数(段数) void PN(int *a);//printf 大整数a void copy(int *a, int *b);// a=b void add(int *a,int *b,int *c);//大整数+大整数 c=a+b void sub(int *a, int *b, int *c);//大整数a-大整数 b,a>b void mult(int *a, int b, int *d);//大整数*整数 c=a*b void mult(int *a,int *b,int *c);//大整数*大整数 c=a*b int Div(int *a,int b,int *c);// c=a/b k=a%b void Div(int *a,int *b,int *c,int *r);// c=a/b r=a%b void gcd(int *a,int *b,int *d);// d=gcd(a,b) /*串-->数 base=10000,A[1]是最低位,A[0]是位数(段数) 串12355558888-->A[1]=8888,A[2]=5555,A[3]=123 A[0]=3,每段 seg=4个数字 */ void trans(char *ch,int *A) {int L,i,j,k,s,i9,seg=4; //seg=6;//Base==1000000 L=strlen(ch); s=L-seg;k=1; for(i=s;i>=0;i-=seg,k++) {i9=i+seg;A[k]=ch[i]-'0'; for(j=i+1;j<i9;j++)A[k]=A[k]*10+ch[j]-48; } i+=seg; A[k]=0; for(j=0;j<i;j++)A[k]=A[k]*10+ch[j]-48; if(A[k])A[0]=k;else A[0]=k-1; } //大整数比较大小 int comp(int *a, int *b) { int i; if (a[0] > b[0])return 1; if (a[0] < b[0])return -1; for (i = a[0]; i >= 1; i--) { if (a[i] > b[i])return 1; if (a[i] < b[i])return -1; } return 0; } int comp(int *a, int *b,int t) { int i,j=1; for (i = b[0]; i >= 1; i--,j++) { if (a[t] > b[i])return j; if (a[t] < b[i])return -1; t--; } return 0; } void PN(int *a){ int i;//输出 "%04d" 10000进制 printf("%d", a[a[0]]); for(i=a[0]-1;i>=1;i--)printf("%04d", a[i]);printf("\n"); } void copy(int *a, int *b) { int i; //a=b for (i = 0;i<= b[0]; ++i)a[i] = b[i]; } //大整数+大整数 c=a+b,Base进制 ,Base=10000 // c[0] 是段数,c[1]是最低位。 // 例9912348888, c[0]=3,c[1]=8888,c[2]=1234,c[3]=99 void add(int *a, int *b, int *c) { int s, i,t,p,d[1000]; if((b[0]==1)&&(b[1]==0)){copy(c,a);return;} if((a[0]==1)&&(a[1]==0)){copy(c,b);return;} if (a[0] >= b[0]) { copy(c,a);copy(d,b);} else { copy(c,b);copy(d,a);} s=c[0];t=d[0];//c[0]>=d[0] c[s + 1] = 0; for (i = 1; i <= t; i++) {c[i]+=d[i]; if (c[i]>=Base){c[i]-=Base;c[i+1]++;} } for (; i <= s; i++){if(c[i]>=Base){c[i] -= Base;c[i+1]++;} else break;} if (c[s+1]>0)c[0] = s + 1;//处理最后一位 } //大整数a-大整数 b, a>b,c=a-b void sub(int *a, int *b, int *c) { int i, j,p=0; if(b[0]==1&&(b[1]==0)){copy(c,a);return;} if(comp(a,b)<=0){copy(c,ZERO);return;} if(comp(a,ZERO)==0){copy(c,ZERO);return;} for (i = 1; i <= b[0]; i++) { c[i] = a[i] - b[i] - p; if (c[i] < 0) { c[i] += Base; p = 1; } else p = 0; } for (; i <= a[0]; i++) { c[i] = a[i] - p; if (c[i] < 0) { c[i] += Base; p = 1; } else p = 0; } for(i=a[0];i>=1;i--){ if (c[i]) {c[0] = i;break;} } } //大整数a乘常数 b b<Base, d=a*b void mult(int *a,int b,int *d) { int w, i,p; if(b==1){copy(d,a);return;} if((b==0)||(a[0]==1&&a[1]==0)){d[0]=1;d[1]=0;return;} w = a[0]; p = 0; // for (i = 1; i <= w; i++) { d[i] = a[i] * b + p; if (d[i] >= Base) { p = d[i] / Base; d[i] %= Base;}else p=0; } if (p) {w++;d[w] = p;} d[0] = w; } //大整数a*大整数 b, c=a*b void mult(int *a,int *b,int *c) {int i,j,s,m,n,k,p;//Base<=10000 m=a[0];n=b[0];k=m+n-1; /*m位数 *n位数 = m+n-1位 或 m+n 位数 实例 12345678*123456789012 =1524157764056090136 a[0]=2 a[1]=5678;a[2]=1234; b[0]=3 b[1]=9012; b[2]=5678;b[3]=1234; */ p=0; for(i=0;i<=k;i++)c[i]=0;c[i]=0; // a[1],a[2]....,a[m] // b[1] // c[1],c[2],...,c[m] for(j=1;j<=n;j++) { s=j; if(b[j])for(i=1;i<=m;i++,s++) {c[s]+=a[i]*b[j]; if(c[s]>=Base){c[s+1]+=c[s]/Base;c[s]%=Base;} } } for(i=1;i<=k;i++)if(c[i]>=Base) { c[i+1]+=c[i]/Base;c[i]%=Base; } if(c[k+1])k++; c[0]=k; } // c=a/b k=a%b int Div(int *a,int b,int *c) {int i,j,s,t; int k=0,q; // long long k=0,q; Base>=100000 if(comp(a,ZERO)==0){copy(c,ZERO);return 0;} for(i=a[0];i>=1;i--) {q=k*Base+a[i]; c[i]=q/b;k=q%b; } if(c[a[0]]==0) { c[0]=a[0]-1; }else c[0]=a[0]; return k; } // 大整数除大整数 c=a/b, r=a%b void Div(int *a,int *b,int *c,int *r) {int m=a[0],n=b[0],i,j,k,s,t,p,q,x,y; int Base1000=Base*1000,Base100=Base*100,Base10=Base*10; //m位数除 n位数= k=m-n+1位数 if(comp(a,b)<0){copy(r,a);copy(c,ZERO);return;} k=m-n+1; for(s=k;s>=0;s--)c[s]=0; for(s=k,t=m;s>=1,t>=n;) { p=comp(a,b,t); // a[t]-b ///////////////// if(p<0 && t==n)break; if(p==0){c[s]++; for(j=t;j>=t-n+1;j--)a[j]=0; t-=n;if(t<n)break;s-=n; } if(p>1) { c[s]++;for(j=t,q=n;j>=t-n+1;j--,q--)a[j]-=b[q]; for(j=t-n+1;j<=t;j++){if(a[j]<0){a[j]+=Base;a[j+1]--;} ////////////////// } for(j=t;j>=t-n+1;j--)if(a[j])break; if(j<n)break; s-=t-j; t=j; } if(p<0 && t>n){a[t-1]+=a[t]*Base;a[t]=0;t--;s--;} if(p==1) // 9999 1234 / 1999 9999 x=4 { x=a[t]/(b +1); c[s]+=x;//x< 4999 for(j=t,q=n;q>=1;q--,j--)a[j]-=x*b[q]; for(j=t-n+1;j<=t;j++) { while(a[j]<=-Base1000){a[j]+=Base1000;a[j+1]-=1000;} while(a[j]<=-Base100){a[j]+=Base100;a[j+1]-=100;} while(a[j]<=-Base10){a[j]+=Base10;a[j+1]-=10;} while(a[j]<0){a[j]+=Base;a[j+1]--;} } } } if(c[k]==0)c[0]=k-1; else c[0]=k; for(i=m;i>=1;i--)if(a[i])break; if(i==0)copy(r,ZERO); else { r[0]=i; while(i>=1){r[i]=a[i];i--;} } } // d=gcd(a,b) void gcd(int *a,int *b,int *d) {int p,x[10000],y[10000],c[10000]; p=comp(a,b); if(p<0){copy(x,b);copy(y,a);} else {copy(x,a);copy(y,b);} // x>=b if(comp(y,ZERO)==0) {copy(d,x);return;} copy(d,y); while(1) { Div(x,d,c,y);// c=x/d; y=x%d if(comp(y,ZERO)==0) {return;} if(comp(y,ONE)==0) {copy(d,ONE);return;} copy(x,d); copy(d,y); } }
相关文章推荐
- 高精度模板(大数)
- uva 10494(大数加减乘除取余一条龙模板代码) uva 10023 (大数开方)
- 大数运算模板
- HDU5351大数模板加斐波那契
- nyoj164 Game of Connections(Catalan数、大数乘法) 模板
- hdu 1134 大数模板
- 我只是来存捡来的大数模板的...
- hdu 5429 Geometric Progression(存个大数模板)
- 大数相乘模板
- A + B Problem II 大数相加(可以作为模板题)
- 大数模板1
- hdu 5429(大数模板)
- Algorithm学习笔记 --- 大数阶乘算法模板
- C++ 大数类 大数模板
- HDU 1715 使用大数模板
- HDU 1041 递推 + 大数模板
- 大数模板
- 大数加法模板
- 用c++类写的大数加法模板
- poj1811-模板题。大数分解+大质数测试(费马+rho)