当我想敲高精加

天道好轮回,苍天饶过谁
今天机房里昊哥敲高精时我不厚道地笑了
结果好家伙,晚上就遇上一道用高精的题

我原来的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	char m[11111],n[11111];
	int a[11111]={0},b[11111]={0},c[11111]={0},i,x,y,flag,d=0;
	scanf("%s%s",m,n);
	x=strlen(m);
	y=strlen(n);
	for(i=0;i<x;i++){
		a[i]=m[x-i-1]-'0';
	}for(i=0;i<y;i++){
		b[i]=n[y-i-1]-'0';
	}if(x<y){
		flag=y;
	}else{
		flag=x;
	}for(i=0;i<flag;i++){
		c[i]=(a[i]+b[i]+d)%10;
		d=(a[i]+b[i]+d)/10;
	}if(d!=0){
		printf("%d",d);
	}for(i=flag-1;i>=0;i--){
		cout<<c[i];
	}
	return 0;
}
改进版代码
int n,f[5010][5010],len;
void jiafa(int k)//高精加法
{
	for(int i=1; i<=len; i++)//两数相加
	    f[k][i]=f[k-1][i]+f[k-2][i];
	for(int i=1; i<=len; i++)//进位
	{
		if(f[k][i]>=10)
		{
			f[k][i+1]+=f[k][i]/10;
			f[k][i]=f[k][i]%10;
			if(f[k][len+1]>0)len++;
		}
	}
}
int main()
{
	cin>>n;
	len=1;
	f[1][1]=1;
	f[2][1]=2;
	for(int i=3; i<=n; i++)//开始计算
	    jiafa(i);
	for(int i=len; i>=1; i--)//输出
	    cout<<f[n][i];
	return 0;
}
原来要用字符串,堪称出bug神器, 改进版妙就妙在用二维数组替换了字符串那个恶心玩意。 一维记录进位,一维记录本位数字 好是好就是太浪费空间了何苦呢 ------------

f[1--k][i]num
f[k][1--i]
进位


好吧,继这件事19天后,gg开始讲高精了,先仍然把范围限制在(花式)高精加上
然后吧,就有了两个神奇的东西

  • 一个是把几个数组改成了结构体(比开二维省空间多了)
  • 一个是万进制
点击查看代码1
struct bignum
{ int len,num[11111]; }a,b,c;

void num(string s,bignum &c)
{
	 reverse(s.begin(),s.end());
	 for(int i=0;i<s.size();i++)
	 {
	 	c.num[i+1]=s[i]-'0';
	 }
	 c.len=s.size();
}
void gaojingjia(bignum a,bignum b)
{
	if(a.len<b.len)int l=b.len;
	else int l=a.len;
	int d;
	for(int i=1;i<=l;i++)
	{
		c.num[i]+=(a.num[i]+b.num[i]+d)%10;
		d=c.num[i]/10;
	}
	if(c.num[l+1]!=0)l++;
	c.len=l;
	print(c);
}
void print(bignum c)
{
	for(int i=c.len;i>0;i--)
	{
		 printf("%d",c.num[i]);
	}
}
点击查看代码2
#include<bits/stdc++.h>
using namespace std;
char m[11111],n[11111];
int a[11111]={0},b[11111]={0},c[11111]={0};
bool book[11111]={0}; 
int l1,l2,flag,d=0,j,k;
int main(){
	scanf("%s%s",m,n);
	l1=strlen(m);
	l2=strlen(n);
	j=0;
	for(int i=0;i<l1;i+=5)
	{
		a[j]=10000*(m[l1-i-1]-'0');
		a[j]=1000*(m[l1-i]-'0');
		a[j]=100*(m[l1-i+1]-'0');
		a[j]=10*(m[l1-i+2]-'0');
		a[j]=m[l1-i+3]-'0';
		j++
	}
	k=0;
	for(int i=0;i<l2;i+=5)
	{
		b[k]=10000*(n[l2-i-1]-'0');
		b[k]=1000*(n[l2-i]-'0');
		b[k]=100*(n[l2-i+1]-'0');
		b[k]=10*(n[l2-i+2]-'0');
		b[k]=n[l2-i+3]-'0';
		k++;
	}
	if(l1<l2)
	{
		flag=k;
	}
	else
	{
		flag=j;
	}
	for(int i=0;i<flag;i++){
		c[i]=(a[i]+b[i]+d)%10000;
		d=(a[i]+b[i]+d)/10000;
		k++;
	}
	if(d!=0)
	{
		printf("%d",d);
	}	
	printf("%d",a[flag-1]);//最高位不需要补零;
	for(i=k-1;i>=1;--i)//从第二个元素
	{
		if(a[i]>=1000)//若该元素是四位数,则原样输出
			printf("%d",a[i]);
		else if(a[i]>=100&&a[i]<1000)//若该元素为三位数,补一个0;
			printf("0%d",a[i]);
		else if(a[i]>=10&&a[i]<100)//补两个;
			printf("00%d",a[i]);
		else//补三个;
			printf("000%d",a[i]);
	}
	return 0;
}
关于万进制这个事儿吧,有人说:"只要了解思路后,也可以扩展“十万进制”甚至更大的进制,更进一步节省内存,减少运算次数 " 但是你说人家创造者能想不到吗?所以我更倾向于万进制是效率最高的——就像那种阿尔法约等于4之类的,经过了复杂的计算与实验(?) 然后接下来是高精减乘除
点击查看高精减(注意前补0)
#include<bits/stdc++.h>
using namespace std;
char m[11111],n[11111];	
int a[11111]={0},b[11111]={0},i,x,y,flag=1;
int main(){
	cin>>m>>n;
	x=strlen(m);
	y=strlen(n);
	for(i=0;i<x;i++){
		a[i]=m[x-i-1]-'0';
	}for(i=0;i<y;i++){
		b[i]=n[y-i-1]-'0';
	}if(x<y){
		flag=0;
	}else if(x>y){
		flag=1;
	}else{
		for(int j=y-1;j>=0;j--){
			if(b[j]>a[j]){
				flag=0;
				break;
			}else if(a[j]>b[j]){
				flag=1;
				break;
			}else{
				flag=2;
			}
		}
	}
	if(flag==0){
		printf("-");
		for(i=0;i<y;i++){
			b[i]=b[i]-a[i];
			if(b[i]<0){
				b[i]=b[i]+10;
				b[i+1]--;
			}
		}i=y-1;
		while(b[i]==0){
			i--;
		}for(;i>=0;i--){
			cout<<b[i];
		}
	}else if(flag==2){
		printf("0");
	}else{
		for(i=0;i<x;i++){
			a[i]=a[i]-b[i];
			if(a[i]<0){
				a[i]=a[i]+10;
				a[i+1]--;
			}
		}i=x-1;
		while(a[i]==0){
			i--;
		}for(;i>=0;i--){
			cout<<a[i];
		}
	}
	return 0;
}
点击查看高精乘(双高精)
#include<bits/stdc++.h>
using namespace std;
int l1,l2,a[11111],b[11111],c[11111],d;
char m[11111]=,n[11111]=;
int main(){
	cin>>m>>n;
	l1=strlen(m);
	l2=strlen(n);
	for(int i=1;i<=l1;++i)
	{
		a[i]=m[l1-i]-'0';
	}
	for(int i=1;i<=l2;++i)
	{
		b[i]=n[l2-i]-'0';
	}
	for(int i=1;i<=l1;++i)
	{
		for(j=1;j<=l2;++j)
		{
			c[i+j-1]+=a[i]*b[j];
		}
	}
	d=n1+n2;
	for(int i=1;i<d;++i)
	{
		if(c[i]>9)
		{
			c[i+1]=c[i+1]+c[i]/10;
			c[i]=c[i]%10;
		}
	}
	while(c[d]==0&&d>1)
	{
		d--;
	}
	for(int i=d;i>=1;--i)
	{
		cout<<c[i];
	}
	return 0;
}
点击查看高精乘(单精*高精)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;
struct bignum
{ int len,num[11111]; }a,b,c;
void num(string s)
{
	 reverse(s.begin(),s.end());
	 for(int i=0;i<s.size();i++)
	 {
	 	a.num[i+1]=s[i]-'0';
	 }
	 a.len=s.size();
}
void cheng(int b)
{
	int l=a.len;
	memset(c.num,0,sizeof(c.num));
	if(b==0)
	{
		c.len=1;
		return;
	}
	for(int i=1;i<=l;i++)
	{
		c.num[i]+=(b*a.num[i]);
		if(c.num[i]>=10)
		{
			c.num[i+1]=c.num[i]/10;
			c.num[i]%=10;
		}
	}
	while(c.num[l]!=0)
	{
		c.num[l+1]+=c.num[l]/10;
		c.num[l++]%=10;
	}
	c.len=l-1;//c是从0开始 
	for(int i=c.len;i>0;i--)
	{
		 printf("%d",c.num[i]);
	}
}
int main()
{
	string s;
	int k;
	cin>>s>>k;
	num(s);
	cheng(k);
	return 0;
}
点击查看高精除
#include<bits/stdc++.h>
using namespace std;
int main(){
	int e[11111]={0},b,c,d[11111]={0},f=0;
	char a[11111]="0";
	cin>>a;
	c=strlen(a);
	scanf("%d",&b);
	for(int i=0;i<c;i++){
		e[i]=a[i]-'0';
	}for(int j=0;j<c;j++){
		d[j]=e[j]/b;
		e[j+1]=e[j]%b*10+e[j+1];
	}for(int k=0;k<c;k++){
		if(d[k]==0&&f==0){
			continue;
		}else{
			printf("%d",d[k]);
		}
		if(d[k]!=0){
			f=1;
		}
	}
	return 0;
}
—————————————————————————————————————————————————————————————————————————————— 还有一点小小的不愉快在于转进制——对此我想说:STL大法好啊!!! strtol(字符串,NULL,要转的进制),返回值就是结果。。。但是不能用。。。这是c++.17版但是考试是14。。。所以还是要老老实实写代码。。。
posted @ 2021-11-06 22:11  fervency  阅读(24)  评论(0编辑  收藏  举报