算法学习(一)(大数运算)(大数相加、大数相减、大数相乘、大数相除(取模、取余)、大数阶乘(求位数、求值))

一、大数相乘

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
	char chr1[100],chr2[100];
	int len1,len2;
	while(scanf("%s %s",chr1,chr2))
	{
		int i,j=0,k=0,s;
		int a[110]={0},b[110]={0},c[220]={0};
		len1=strlen(chr1);
		len2=strlen(chr2);
		for(i=len1-1,j=0;i>=0;i--) a[j++]=chr1[i]-'0';
		for(i=len2-1,k=0;i>=0;i--) b[k++]=chr2[i]-'0';
		for(i=0;i<len1;i++)
		{
			for(s=0;s<len2;s++)
			{
				c[i+s]=c[i+s]+a[i]*b[s];
			}
		}
		for(i=0;i<200;i++)
		{
			if(c[i]>=10){
				c[i+1]=c[i+1]+c[i]/10;  //这一步和下面一步位置不要写反了
				c[i]=c[i]%10;
			}
		}
		for(i=200;i>0;i--)
		{
			if(c[i]==0) continue;
			else break;
		}
		for(;i>=0;i--) cout<<c[i];
		cout<<endl;
	}
	return 0;
}

 二、大数相除(取模,取余)(没有看懂)

#include<stdio.h>
#include<string.h>
char a[100],b[100];//用两个字符串用来输入两个大数 
int x[100],y[100],z[100],m[100];//被除数  除数  商  余数 
int digit;//大数的位数 
void sub(int x[],int y[],int len1,int len2)//大数减法 
{
	int i;
	for(i=0;i<len1;i++)
	{
		if(x[i]<y[i])
		{
			x[i]=x[i]+10-y[i];
			x[i+1]--;
		}
		else
			x[i]=x[i]-y[i];
	}
	for(i=len1-1;i>=0;i--)//判断减法结束之后,被除数的位数 
	{
		if(x[i])
		{ 
			digit=i+1;
			break;		   
		} 
	}
}
int judge(int x[],int y[],int len1,int len2)
{
	int i;
	if(len1<len2)
		return -1;
	if(len1==len2)//若两个数位数相等 
	{
		for(i=len1-1;i>=0;i--)
		{
			if(x[i]==y[i])//对应位的数相等 
				continue;
			if(x[i]>y[i])//被除数 大于 除数,返回值为1 
				return 1;
			if(x[i]<y[i])//被除数 小于 除数,返回值为-1 
				return -1;
		}
		return 0;//被除数 等于 除数,返回值为0 
	}	
}
int main()
{
	int i,j=0,k=0,temp;
	int len1,len2,len;//len两个大数位数的差值   
	while(~scanf("%s %s",a,b))
	{
		len1=strlen(a);//被除数位数
		len2=strlen(b);//除数位数
		for(i=len1-1,j=0;i>=0;i--)//将字符串中各个元素倒序储存在数组中 
			x[j++]=a[i]-'0';
		for(i=len2-1,k=0;i>=0;i--)
			y[k++]=b[i]-'0';		    
		if(len1<len2)//当被除数位数 小于 除数位数时 
		{
			printf("商是:0\n");
			printf("余数是:");
			puts(a); 
		}
		else //当被除数位数 大于或者 除数位数时
		{
			len=len1-len2;//两个大数位数的差值
			for(i=len1-1;i>=0;i--)//将除数后补零,使得两个大数位数相同。被除数:4541543329 除数:98745,加零后:9874500000 
			{
				if(i>=len)
					y[i]=y[i-len];
				else
					y[i]=0;
			}
			len2=len1;//将两个大数数位相同 		
			digit=len1;	//将原被除数位数赋值给digit 
			for(j=0;j<=len;j++)
            {
				z[len-j]=0;
				while(((temp=judge(x,y,len1,len2))>=0)&&digit>=k)//判断两个数之间的关系以及位数与除数原位数的关系 
				{	
					sub(x,y,len1,len2);	//大数减法函数			    
					z[len-j]++;//储存商的每一位
					len1=digit;//重新修改被除数的长度
					if(len1<len2&&y[len2-1]==0)		
						len2=len1;//将len1长度赋给len2;						
				}
				if(temp<0)//若被除数 小于 除数,除数减小一位。例如:被除数:4541543329 除数:(原)98745,(加零后)9874500000,后退一位后:0987450000 
				{
					for(i=1;i<len2;i++)
						y[i-1]=y[i];
					y[i-1]=0;
					if(len1<len2) 
						len2--;			        				        
				}
			}
			printf("商是:");
			for(i=len;i>0;i--)//去掉前缀0 
			{
				if(z[i])
					break;
			}
			for(;i>=0;i--)
				printf("%d",z[i]);
			printf("\n");
			printf("余数是:");
			for(i=len1;i>0;i--)
			{
				if(x[i])
					break;
			}
			for(;i>=0;i--)
				printf("%d",x[i]);
			printf("\n");
		}
	}
	return 0;
}  

三、大数阶乘(求位数)

法一:

lg(N!)=[lg(N*(N-1)*(N-2)*......*3*2*1)]+1 =[lgN+lg(N-1)+lg(N-2)+......+lg3+lg2+lg1]+1

#include<stdio.h>
#include<math.h>
int main()
{
	int n;
	double sum=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		sum=sum+log10(i);
	}
	printf("%d\n",(int)sum+1);
	return 0;
}  

法二:

log10(n!) = log10(2*PI*n)/2+n*log10(n/E); 
故n!的位数= log10(2*PI*n)/2+n*log10(n/E)+1(注意:当n=1时,算得的结果为0)

#include<stdio.h>
#include<math.h>
#define PI 3.141592654
#define E 2.71828182846
int main()
{
	int n,sum=1;
	scanf("%d",&n);
	if(n>3)
		sum=log10(2*PI*n)/2+n*log10(n/E)+1;
	printf("%d\n",sum);
	return 0;   
}  

四、大数阶乘(求值)

 

#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
	int n,a[20001];
	int temp,digit=1;
	a[0]=1;
	cin>>n;
	int i,j;
	for(i=2;i<=n;i++)
	{
		int num=0;
		for(j=0;j<digit;j++)
		{
			temp=a[j]*i+num;
			a[j]=temp%10;
			num=temp/10;
		}
		while(num)
		{
			a[digit]=num%10;
			num/=10;
			digit++;
		}
	}
	for(i=digit-1;i>=0;i--) cout<<a[i];
	cout<<endl;
	return 0;
}

 

五、大数相减

//大数相减
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int x[100]={0},y[100]={0},z[100]={0};
void sub(int x[],int y[],int len)
{
	for(int i=0;i<len;i++)
	{
		if(x[i]>=y[i]) z[i]=x[i]-y[i];
		else if(x[i]<y[i])
		{
			z[i]=x[i]+10-y[i];
			x[i+1]=x[i+1]-1;
		}
	}
	for(int i=len-1;i>0;i--)
	{
		if(z[i]==0) len--;
		else break;
	}
	for(int i=len-1;i>=0;i--) cout<<z[i];
	cout<<endl;
}
int main()
{
	char chr1[100],chr2[100];
	int len1,len2;
	while(scanf("%s %s",chr1,chr2))
	{
		
		int i,j=0,k=0;
		len1=strlen(chr1);
		len2=strlen(chr2);
		for(i=len1-1,j=0;i>=0;i--) x[j++]=chr1[i]-'0';
		for(i=len2-1,k=0;i>=0;i--) y[k++]=chr2[i]-'0';
		if(len1>len2) sub(x,y,len1);
		else if(len1<len2) 
		{
			printf("-");
			sub(y,x,len2);
		}
		else if(len1==len2)
		{
			for(i=len1-1;i>=0;i--)
			{
				if(x[i]==y[i]) continue;
				else if(x[i]>y[i])
				{
					sub(x,y,len1);
					break;
				}
				else if(x[i]<y[i])
				{
					printf("-");
					sub(y,x,len1);
					break;
				}
			}
		    if(i==-1) sub(x,y,len1);
		}
	}
	return 0;
 }   

六、大数相加

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
	char chr1[100],chr2[100];
	int a[100]={0},b[100]={0},c[100]={0};
	int len1,len2,len;
	while(scanf("%s %s",chr1,chr2))
	{
		int i,j=0,k=0;
		len1=strlen(chr1);
		len2=strlen(chr2);
		for(i=len1-1;i>=0;i--) 
		{
			a[j]=chr1[i]-'0';
			j++;
		}
		for(i=len2-1;i>=0;i--)
		{
			b[k]=chr2[i]-'0';
			k++;
		}
		if(len1>len2) len=len1;
		else len=len2;
		int m=0;
		for(i=0;i<len;i++)
		{
			c[i]=(a[i]+b[i]+m)%10;
			if(a[i]+b[i]+m>=10) m=1;
			else m=0;
		}
		if(a[i-1]+b[i-1]+m>10) c[i]=1;
		else i=i-1;
		for(;i>=0;i--) cout<<c[i];
		cout<<endl;
	}
	return 0;
 }
posted @ 2019-12-19 12:39  yyer  阅读(540)  评论(0编辑  收藏  举报