引入
在数字运算中,有时候a*b连long long 都装不下,这个适合,就需要用到高精度了。
例题1
P2955 [USACO09OCT]Even? Odd? G
分析
判断一个数的奇偶,即判断能否被2整除,其实也就只需要判断末位数字是否为2的倍数。
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++){
char a[65];scanf("%s",a);//long long装不下,用字符串
int c=strlen(a);
int s=a[c-1]-'0';//求末位数字
if(s%2==0)printf("even\n");//判断整除
else printf("odd\n");
}
}
例题2
题目描述
输入长度(超过14,小于99)的两个正数,输出两个数的和。
输入
两行
第一行,一个数
第二行,一个数
输出
一行
输入的两个数的和
样例输入
900000000000000
1111111111111111
样例输出
2011111111111111
分析
这道题一看,即使看long long 也一定会爆精度,但我们可以参考例题1的方法,用字符串存数,进行字符串运算。也就是高精度加法。
代码
#include<bits/stdc++.h>
using namespace std;
#define N 100+5
#define INF 0x3f3f3f3f
#define full(a,b) memset(a,b,sizeof a)
void init(int x[]){
string s;cin>>s;
x[0]=s.size();
for(int i=1;i<=x[0];i++)
x[i]=s[x[0]-i]-'0';//转化为数字,并且逆序储存
}
int main(){
int a[N],b[N],c[N];
full(a,0);full(b,0);full(c,0);//记得初始化
init(a);init(b);//输入
int pos=1,x=0;
while(pos<=a[0]||pos<=b[0]){
c[pos]=a[pos]+b[pos]+x;
x=c[pos]/10;
c[pos]%=10;
++pos;
}c[pos]=x,c[0]=pos;//高精度加法模板
while(c[0]>1&&c[c[0]]==0)c[0]--;//去掉前导0
for(int i=c[0];i>=1;i--)//逆序输出
printf("%d",c[i]);
}
例题3
分析
题目已经暴露了一切,就直接上代码了。
代码
#include<bits/stdc++.h>
using namespace std;
#define N 100+5
#define INF 0x3f3f3f3f
#define full(a,b) memset(a,b,sizeof a)
void init(int x[]){//读入
char s[N];cin>>s;
x[0]=strlen(s);
for(int i=1;i<=x[0];i++)
x[i]=s[x[0]-i]-'0';
}
int numcmp(int x[],int y[]){//比较大小
if(x[0]<y[0])return -1;
if(x[0]>y[0])return 1;
for(int i=x[0];i>=1;i--)
if(x[i]>y[i])return 1;
else if(x[i]<y[i])return -1;
return 0;
}
void numcpy(int x[],int y[],int pos){//把x赋值给y,并把y乘 10的pos次方
y[0]=x[0]+pos-1;
for(int i=1;i<=x[0];i++)
y[i+pos-1]=x[i];
}
int main(){
int a[N],b[N];
full(a,0);full(b,0);//记得初始化
init(a);init(b);
if(numcmp(a,b)<0){//a比b小
int k[N];
full(k,0);numcpy(a,k,1);
full(a,0);numcpy(b,a,1);
full(b,0);numcpy(k,b,1);//交换两数
cout<<"-";//结果为负数
}
int i=1;
while(i<=a[0]){
if(a[i]<b[i])a[i]+=10,a[i+1]--;
a[i]-=b[i];++i;
}//高精度减法模板
while(a[0]>1&&a[a[0]]==0)a[0]--;
for(int i=a[0];i>=1;i--)
printf("%d",a[i]);
}
高精度乘法
题目描述
输入两个高精度非负整数m和n(m和n均小于100位),求这两个高精度数的积。
输入
输入两个高精度正整数m和n(m和n均小于100位)
输出
输出两个高精度数的积
样例输入
36
3
样例输出
108
代码
#include<bits/stdc++.h>
using namespace std;
#define N 100+5
#define INF 0x3f3f3f3f
#define full(a,b) memset(a,b,sizeof a)
void init(int x[]){//读入
char s[N];cin>>s;
x[0]=strlen(s);
for(int i=1;i<=x[0];i++)
x[i]=s[x[0]-i]-'0';
}
int main(){
int a[N],b[N],c[N];
full(a,0);full(b,0);full(c,0);
init(a);init(b);
for(int i=1;i<=a[0];i++){
int x=0;
for(int j=1;j<=b[0];j++){
c[i+j-1]+=a[i]*b[j]+x;
x=c[i+j-1]/10;
c[i+j-1]%=10;
}c[i+b[0]]+=x;
}c[0]=a[0]+b[0];
//模板
while(c[0]>1&&c[c[0]]==0)c[0]--;
for(int i=c[0];i>=1;i--)
printf("%d",c[i]);
}
高精度除法
代码
#include<bits/stdc++.h>
using namespace std;
#define N 100000+5
#define INF 0x3f3f3f3f
#define full(a,b) memset(a,b,sizeof a)
#define gaoji(x) while(x[0]>1&&x[x[0]]==0) --x[0];//去前导0
void init(int x[]){//读入
char s[N];cin>>s;
x[0]=strlen(s);
for(int i=1;i<=x[0];i++)
x[i]=s[x[0]-i]-'0';
}
void numcpy(int x[],int y[],int pos){//数组的拷贝
y[0]=x[0]+pos-1;
for(int i=1;i<=x[0];i++)
y[i+pos-1]=x[i];
}
int numcmp(int x[],int y[]){//比较大小
if(x[0]>y[0])return 1;
if(x[0]<y[0])return -1;
for(int i=x[0];i>=1;i--)
if(x[i]>y[i])return 1;
else if(x[i]<y[i])return -1;
return 0;
}
void jian(int x[],int y[]){//减法
int k=1;
while(k<=x[0]){
if(x[k]<y[k])x[k]+=10,x[k+1]--;
x[k]-=y[k];++k;
}
gaoji(x);
}
void print(int a[])//输出
{
if(a[0]<=0) printf("0");
for(int i=a[0];i>=1;i--)
printf("%d",a[i]);
puts("");
}
int main(){
int a[N],b[N],c[N];
full(a,0);full(b,0);full(c,0);
init(a);init(b);
c[0]=a[0]-b[0]+1;
for(int k=c[0];k>=1;k--){
int tmp[N];
full(tmp,0);
numcpy(b,tmp,k);//末位对齐
while(numcmp(a,tmp)>=0)
{c[k]++;jian(a,tmp);}//除法变减法
}
//模板
gaoji(c);
print(c);
}
高精*单精
void cheng(int a[],int x)//a*x
{
for(int i=1; i<=a[0]; i++) a[i]*=x;//先乘
for(int i=1; i<=a[0]; i++)
{
a[i+1]+=a[i]/10;//再加
a[i]%=10;
}
++a[0];//可能进位
while(a[a[0]]>9)//处理进位
{
a[a[0]+1]+=a[a[0]]/10;
a[a[0]]%=10;
++a[0];
}
gaoji(a);
}
高精/单精
void chu(int a[],int x)//a/x
{
for(int i=a[0]; i>=1; i--)//从高到低除
{
if(i>1) a[i-1]+=a[i]%x*10;//第0位不改变
a[i]/=x;
}
gaoji(a);
}
总结
高精度在很多时候都起到了作用,是一个很可恶的优秀的算法,但是高精度太频繁也会时间超限,要谨慎使用。