您的位置:首页 > 其它

周教授大数模板【完整版】

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);
}
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: