1. 程式人生 > >51nod_1005 大數加法/HDU1753 大明A+B/poj1001(大數的加法/減法/乘法)

51nod_1005 大數加法/HDU1753 大明A+B/poj1001(大數的加法/減法/乘法)

先系統的講講大數加法減法乘法的統一套路:

先貼程式碼:

大數加法

void BigAdd(char *adda,int lena,char *addb,int lenb,char sum[]){
	int i,j,lensum;
	lensum=lena>lenb?lena:lenb;
	char *result,final[N];
	lensum++;
	result=(char *)calloc(lensum,1);
	lensum--;
	for(i=0;i<lena;i++)
		adda[i]-='0';
	for(i=0;i<lenb;i++)
		addb[i]-='0';
	for(i=0;i<lena&&i<lenb;i++)
		result[i]=adda[lena-i-1]+addb[lenb-i-1];
	if(lena>lenb)
		for(i=lenb;i<lena;i++)
			result[i]=adda[lena-i-1];
	if(lena<lenb)
		for(i=lena;i<lenb;i++)
			result[i]=addb[lenb-i-1];			
	for(i=0;i<lensum;i++){
		if(result[i]>9){
			int t=result[i]/10;
			result[i]%=10;
			result[i+1] += t ;
		}
	}			
	j=0;
	if(result[lensum]!=0){
		final[j]=result[lensum]+'0';
		j++;
	}		
	for(i=lensum-1;i>=0;i--)
		final[j++]=result[i]+'0';
		
	final[j]='\0';	
	strcpy(sum,final);			
} 

大數減法:

void BigSub(char *suba,int lena,char *subb,int lenb,char sum[]){  
	int lensum,num='0';
	int i,j,k,tmp;
	lensum=lena>lenb?lena:lenb;
	for(i=0;i<lena;i++){                                  
		suba[i]=suba[i]-num;                               
	}
	for(i=0;i<lenb;i++){
		subb[i]=subb[i]-num;
	}
	char *result,final[N];
	result=(char*)calloc(lensum,1);                      
	for(i=0,j=0;i<lena&&j<lenb;i++,j++){                 
		result[i]=suba[lena-i-1]-subb[lenb-i-1];          
	}
	if(lena>lenb){                        
		for(i=lenb;i<lena;i++){
		   result[i]=suba[lena-i-1];
		}
	}
	if(lenb>lena){                        
		for(i=lena;i<lenb;i++){
		   result[i]=subb[lenb-i-1];
		}
	}
	for(k=0;k<lensum-1;k++){            
		if(result[k]<0){
		   result[k]=result[k]+10;
		   result[k+1]-=1;
		}
	}
	j=0;
    if(result[lensum-1]!=0){             
		final[j]=result[lensum-1]+num;
		j++;
	}
    for(i=lensum-2;i>=0;i--)
        final[j++]=result[i]+num;
 
	final[j]='\0';
	strcpy(sum,final);
}

大數乘法:

void bigmul(char *f,int lena,char *m,int lenb,char *final){
	int i,j,k,tmp_result,lensum;
	lensum=lena+lenb;
	for(i=0;i<lena;i++)
		f[i]-='0';
	for(i=0;i<lenb;i++)
		m[i]-='0';
	char *result;
	result=(char *)calloc((lensum+1),sizeof(char));
	for(i=0;i<lena;i++){
		for(j=0;j<lenb;j++){
			tmp_result=f[lena-i-1]*m[lenb-j-1];
			result[i+j]+=tmp_result;
		}
		for(k=0;k<=i+j-1;k++){
			if(result[k]>9){
				int item;
				item=result[k]/10;
				result[k]%=10;
				result[k+1]+=item;
			}
		}
	}
	j=0;
	if(result[lensum-1]!=0){
		final[j++]=result[lensum-1]+'0';
	}
	
	for(i=lensum-2;i>=0;i--){
		final[j++]=result[i]+'0';
	}
	final[j]='\0';				
}

這三個程式碼比較,你會發現他們的共同之處:

首先對傳進來的兩個字串作處理,在逆序相加儲存在result數組裡面,然後對result陣列處理即可。三個程式碼,只有對result陣列的處理不同。

這樣得出來的答案一般含有前導0,所有你需要一個函式除去前導0

void f(char sum[])
{
	char a[N];
	strcpy(a,sum);
	int i;
	int flag=0;
	int len=strlen(a);
	for(i=0;i<len;i++)
		if(a[i]!='0')
		{
			flag=1;
			break;
		}
	if(flag==0)
	{
		strcpy(sum,"0");
	}else{
		char s[N];
		int t;
		for(i=0;i<len;i++)
		{
			if(a[i]!='0')
			{
				t=i;
				break;
			}
		}
		int j=0;
		for(i=t;i<len;i++)
		{
			s[j++]=a[i];
		}
		s[j]='\0';
		strcpy(sum,s);
	}
}

大數加法

給出2個大整數A,B,計算A+B的結果。

Input

第1行:大數A
第2行:大數B
(A,B的長度 <= 10000 需注意:A B有可能為負數)

Output

輸出A + B

Sample Input

68932147586
468711654886

Sample Output

537643802472

題解:這一題很明顯是考察大數的加法和減法,但是這種題卻最不容易做,很是讓人頭痛,博主也是寫了半天才AC。因為測試資料很雜,只有細心分好類,才能AC。主要去掉前導0.

比如測試資料:00001 0000003,0 -0,100 -99,10000 -999

具體程式碼如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 10010
void BigAdd(char *adda,int lena,char *addb,int lenb,char sum[]){//加法
	int i,j,lensum;
	lensum=lena>lenb?lena:lenb;
	char *result,final[N];
	lensum++;
	result=(char *)calloc(lensum,1);
	lensum--;
	for(i=0;i<lena;i++)
		adda[i]-='0';
	for(i=0;i<lenb;i++)
		addb[i]-='0';
	for(i=0;i<lena&&i<lenb;i++)
		result[i]=adda[lena-i-1]+addb[lenb-i-1];
	if(lena>lenb)
		for(i=lenb;i<lena;i++)
			result[i]=adda[lena-i-1];
	if(lena<lenb)
		for(i=lena;i<lenb;i++)
			result[i]=addb[lenb-i-1];			
	for(i=0;i<lensum;i++){
		if(result[i]>9){
			int t=result[i]/10;
			result[i]%=10;
			result[i+1] += t ;
		}
	}			
	j=0;
	if(result[lensum]!=0){
		final[j]=result[lensum]+'0';
		j++;
	}		
	for(i=lensum-1;i>=0;i--)
		final[j++]=result[i]+'0';
		
	final[j]='\0';	
	strcpy(sum,final);			
} 
void BigSub(char *suba,int lena,char *subb,int lenb,char sum[]){ //減法
	int lensum,num='0';
	int i,j,k,tmp;
	lensum=lena>lenb?lena:lenb;
	for(i=0;i<lena;i++){                                  
		suba[i]=suba[i]-num;                               
	}
	for(i=0;i<lenb;i++){
		subb[i]=subb[i]-num;
	}
	char *result,final[N];
	result=(char*)calloc(lensum,1);                      
	for(i=0,j=0;i<lena&&j<lenb;i++,j++){                 
		result[i]=suba[lena-i-1]-subb[lenb-i-1];          
	}
	if(lena>lenb){                        
		for(i=lenb;i<lena;i++){
		   result[i]=suba[lena-i-1];
		}
	}
	if(lenb>lena){                        
		for(i=lena;i<lenb;i++){
		   result[i]=subb[lenb-i-1];
		}
	}
	for(k=0;k<lensum-1;k++){            
		if(result[k]<0){
		   result[k]=result[k]+10;
		   result[k+1]-=1;
		}
	}
	j=0;
    if(result[lensum-1]!=0){             
		final[j]=result[lensum-1]+num;
		j++;
	}
    for(i=lensum-2;i>=0;i--)
        final[j++]=result[i]+num;
 
	final[j]='\0';
	strcpy(sum,final);
}
void f(char sum[])//去掉前導0
{
	char a[N];
	strcpy(a,sum);
	int i;
	int flag=0;
	int len=strlen(a);
	for(i=0;i<len;i++)
		if(a[i]!='0')
		{
			flag=1;
			break;
		}
	if(flag==0)
	{
		strcpy(sum,"0");
	}else{
		char s[N];
		int t;
		for(i=0;i<len;i++)
		{
			if(a[i]!='0')
			{
				t=i;
				break;
			}
		}
		int j=0;
		for(i=t;i<len;i++)
		{
			s[j++]=a[i];
		}
		s[j]='\0';
		strcpy(sum,s);
	}
}
int main()
{
	char a[N],b[N];
	scanf("%s",a);
	scanf("%s",b);
	char sum[N];
	if(a[0]=='-')
	{
		char *p=a;
		char num[N];
		strcpy(num,p+1);
		strcpy(a,num);
		if(b[0]=='-')
		{
			char *p=b;
			char num[N];
			strcpy(num,p+1);
			strcpy(b,num);
			int lena,lenb;
			lena=strlen(a);
			lenb=strlen(b);
			BigAdd(a,lena,b,lenb,sum);
			f(sum);
			if(strcmp(sum,"0")==0)
				printf("0\n",sum);
			else
				printf("-%s\n",sum);
		}
		else
		{
			int lena,lenb;
			lena=strlen(a);
			lenb=strlen(b);
			if(lena>lenb)//a大
			{
				BigSub(a,lena,b,lenb,sum);
				f(sum);
				printf("-%s\n",sum);
		 	}else if(lena<lenb)//a小 
		 	{
		 		BigSub(b,lenb,a,lena,sum);
		 		f(sum);
				printf("%s\n",sum);
			}else{
				if(strcmp(a,b)>0)//a大 
				{
					BigSub(a,lena,b,lenb,sum);
					f(sum);
					printf("-%s\n",sum);
				}else if(strcmp(a,b)<0)//a小 
				{
					BigSub(b,lenb,a,lena,sum);
					f(sum);
					printf("%s\n",sum);
				}else{
					printf("0\n");
				} 
			}
		}
	}else//a為正 
	{
		if(b[0]=='-')
		{
			char *p=b;
			char num[N];
			strcpy(num,p+1);
			strcpy(b,num);
			int lena,lenb;
			lena=strlen(a);
			lenb=strlen(b);
			if(lena>lenb)//a大
			{
				BigSub(a,lena,b,lenb,sum);
				f(sum);
				printf("%s\n",sum); 
			}else if(lena<lenb)//a小
			{
				BigSub(b,lenb,a,lena,sum);
				f(sum);
				printf("-%s\n",sum); 
			}else
			{
				if(strcmp(a,b)>0)//a大
				{
					BigSub(a,lena,b,lenb,sum);
					f(sum);
					printf("%s\n",sum);	
				}else if(strcmp(a,b)<0){//a小 
					BigSub(b,lenb,a,lena,sum);
					f(sum);
					printf("-%s\n",sum);
				}else{
					printf("0\n");
				}
			}
		}else
		{
			int lena,lenb;
			lena=strlen(a);
			lenb=strlen(b);
			BigAdd(a,lena,b,lenb,sum);
			f(sum);
			printf("%s\n",sum);
		}
	}
	return 0;
}

大明A+B

話說,經過了漫長的一個多月,小明已經成長了許多,所以他改了一個名字叫“大明”。
這時他已經不是那個只會做100以內加法的那個“小明”了,現在他甚至會任意長度的正小數的加法。

現在,給你兩個正的小數A和B,你的任務是代表大明計算出A+B的值。

Input

本題目包含多組測試資料,請處理到檔案結束。
每一組測試資料在一行裡面包含兩個長度不大於400的正小數A和B。

Output

請在一行裡面輸出輸出A+B的值,請輸出最簡形式。詳細要求請見Sample Output。

Sample Input

1.1 2.9
1.1111111111 2.3444323343
1 1.1

Sample Output

4
3.4555434454
2.1

題解:將整數部分和小數部分分開來算,然後考慮小數進位的問題,還有要注意去掉小數後導0.

具體程式碼如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#define N 600 
using namespace std;
void BigAdd(char *adda,int lena,char *addb,int lenb,char sum[]){//整數部分加法
	int i,j,lensum;
	lensum=lena>lenb?lena:lenb;
	char *result,final[N];
	lensum++;
	result=(char *)calloc(lensum,1);
	lensum--;
	for(i=0;i<lena;i++)
		adda[i]-='0';
	for(i=0;i<lenb;i++)
		addb[i]-='0';
	for(i=0;i<lena&&i<lenb;i++)
		result[i]=adda[lena-i-1]+addb[lenb-i-1];
	if(lena>lenb)
		for(i=lenb;i<lena;i++)
			result[i]=adda[lena-i-1];
	if(lena<lenb)
		for(i=lena;i<lenb;i++)
			result[i]=addb[lenb-i-1];			
	for(i=0;i<lensum;i++){
		if(result[i]>9){
			int t=result[i]/10;
			result[i]%=10;
			result[i+1] += t ;
		}
	}			
	j=0;
	if(result[lensum]!=0){
		final[j]=result[lensum]+'0';
		j++;
	}		
	for(i=lensum-1;i>=0;i--)
		final[j++]=result[i]+'0';
		
	final[j]='\0';	
	strcpy(sum,final);			
} 
void SmallAdd(char *adda,int lena,char *addb,int lenb,char sum[])//小數部分加法
{
	char *result;
	int lensum=lena>lenb?lena:lenb;
	lensum++;
	result=(char *)calloc(lensum,1);
	lensum--;
	int i;
	for(i=0;i<lena;i++)
		adda[i]-='0';
	for(i=0;i<lenb;i++)
		addb[i]-='0';
	int lenmin=lena<lenb?lena:lenb;
	for(i=0;i<lenmin;i++)
		result[i]=adda[lenmin-i-1]+addb[lenmin-i-1];
	for(i=0;i<lenmin;i++)
		if(result[i]>9)
		{
			result[i+1]++;
			result[i]%=10;
		}
	int j;
	j=0;
	char final[N];
	if(result[lenmin]!=0)
	{
		final[j]=result[lenmin]+'0';
		j++;
	}
	for(i=lenmin-1;i>=0;i--)
		final[j++]=result[i]+'0';
	if(lena>lenb)
		for(i=lenmin;i<lena;i++)
			final[j++]=adda[i]+'0';	
	if(lena<lenb)
		for(i=lenmin;i<lenb;i++)
			final[j++]=addb[i]+'0';	
	final[j]='\0';	
	strcpy(sum,final);	
}
int main()
{
    char num1[N],num2[N];
    while(scanf("%s%s",num1,num2)!=EOF)
    {
    	char a[N],b[N];//儲存小數部分
		char a1[N],b1[N];//儲存整數部分 
		char *p=strchr(num1,'.');
		char *q=strchr(num2,'.');				
		if(p) 
		{
			strcpy(a,p+1);
			*p='\0';
			strcpy(a1,num1);
		}					
		else 
		{
			sscanf("0","%s",a);
			strcpy(a1,num1);
		}				
		if(q) 
		{
			strcpy(b,q+1);
			*q='\0';
			strcpy(b1,num2);
		}				
		else 
		{
			sscanf("0","%s",b);	
			strcpy(b1,num2);
		}		
		int lena=strlen(a);
		int lenb=strlen(b);
		char sum2[N],sum1[N];//加完後的值 
		SmallAdd(a,lena,b,lenb,sum2);//小數相加 
		int lena1=strlen(a1);
		int lenb1=strlen(b1); 
		int len=strlen(sum2);
		int flag=0,temp=0;
		if(len!=lena&&len!=lenb)//如果小數進位了 
		{	temp=1;
			a1[lena1-1]++;
			char *p=sum2,sum3[N];
			p++;			
			strcpy(sum3,p);
			strcpy(sum2,sum3);
			for(int i=0;i<strlen(sum2);i++)
				if(sum2[i]!='0')
				{
					flag=1;//說明不全是0 
					break;
				}
			if(flag==1)
				for(int i=strlen(sum2)-1;i>=10;i--)
					if(sum2[i]!='0')
					{
						sum2[i+1]='\0';
						break;
					} 
		}
		else{
			for(int i=0;i<strlen(sum2);i++)
				if(sum2[i]!='0')
				{
					flag=1;//說明不全是0 
					break;
				}
			if(flag==1)
				for(int i=strlen(sum2)-1;i>=10;i--)
					if(sum2[i]!='0')
					{
						sum2[i+1]='\0';
						break;
					} 
		}
		BigAdd(a1,lena1,b1,lenb1,sum1);//整數相加 		
		if(temp==1)//進位了 
		{
			if(flag==1)
				printf("%s.%s\n",sum1,sum2);
			else
				printf("%s\n",sum1);
		}else{//沒進位 
			if(flag==1)
				printf("%s.%s\n",sum1,sum2);
			else
				printf("%s\n",sum1);	
		}
		
			
		
			
	}
    return 0;
}

Exponentiation

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.

This problem requires that you write a program to compute the exact value of R n where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

大概題意就是每行一個R一個N,求R^N.

題解:這一題應該是這三道題裡面最好過的一道,先把小數點去掉,求出乘積的值,最後根據小數點後面的位數,在輸出的時候把小數點加上就OK了。還有是要注意前導0和後導0的問題。

具體程式碼如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#define N 6000
using namespace std;
void bigmul(char *f,char *m,char *final){//大數乘法
	int i,j,k,tmp_result,lensum;
	int lena=strlen(f);
	int lenb=strlen(m);
	lensum=lena+lenb;
	for(i=0;i<lena;i++)
		f[i]-='0';
	for(i=0;i<lenb;i++)
		m[i]-='0';
	char *result;
	result=(char *)calloc((lensum+1),sizeof(char));
	for(i=0;i<lena;i++){
		for(j=0;j<lenb;j++){
			tmp_result=f[lena-i-1]*m[lenb-j-1];
			result[i+j]+=tmp_result;
		}
		for(k=0;k<=i+j-1;k++){
			if(result[k]>9){
				int item;
				item=result[k]/10;
				result[k]%=10;
				result[k+1]+=item;
			}
		}
	}
	j=0;
	if(result[lensum-1]!=0){
		final[j++]=result[lensum-1]+'0';
	}
	
	for(i=lensum-2;i>=0;i--){
		final[j++]=result[i]+'0';
	}
	final[j]='\0';				
}
void fa(char sum[])//去前導0
{
	char a[N];
	strcpy(a,sum);
	int i;
	int flag=0;
	int len=strlen(a);
	for(i=0;i<len;i++)
		if(a[i]!='0')
		{
			flag=1;
			break;
		}
	if(flag==0)
	{
		strcpy(sum,"0");
	}else{
		char s[N];
		int t;
		for(i=0;i<len;i++)
		{
			if(a[i]!='0')
			{
				t=i;
				break;
			}
		}
		int j=0;
		for(i=t;i<len;i++)
		{
			s[j++]=a[i];
		}
		s[j]='\0';
		strcpy(sum,s);
	}
}
void fb(char sum[])//去後導0
{
	char a[N];
	int len2=strlen(sum);
	int i,j;
	for(i=0;i<len2;i++)
		a[i]=sum[len2-i-1];
	a[i]='\0';
	int flag=0;
	int len=strlen(a);
	for(i=0;i<len;i++)
		if(a[i]!='0')
		{
			flag=1;
			break;
		}
	if(flag==0)
	{
		strcpy(sum,"0");
	}else{
		char s[N];
		int t;
		for(i=0;i<len;i++)
		{
			if(a[i]!='0')
			{
				t=i;
				break;
			}
		}
		int j=0;
		for(i=t;i<len;i++)
		{
			s[j++]=a[i];
		}
		s[j]='\0';
		int len1=strlen(s);
		for(i=0;i<len1;i++)
			a[i]=s[len1-i-1];
		a[i]='\0';
		strcpy(sum,a);
	}
}
int main()
{
    char num1[N];
	int n;
    while(scanf("%s%d",num1,&n)!=EOF)
    {
    	char b[N];//儲存小數部分
		char a[N];//儲存整數部分 
		char final[N];//儲存最終答案 
		strcpy(final,"1");
		char *p=strchr(num1,'.');
		if(p)
		{
			strcpy(b,p+1);
			*p='\0';
			strcpy(a,num1);
		}else{
			strcpy(a,num1);
			strcpy(b,"0");
		}						
		fb(b);
		fa(a);		
		if(strcmp(a,"0")==0)
		{
			if(strcmp(b,"0")==0)
				cout<<"0"<<endl;
			else//.123456 
			{
				int lena=strlen(b)*n;
				for(int i=0;i<n;i++)
				{					
					char p[N],q[N];
					strcpy(p,final);
					strcpy(q,b);
					bigmul(p,q,final);
				}
				int lenb=strlen(final);
				cout<<".";
				for(int i=0;i<lena-lenb;i++)
					cout<<"0";
				cout<<final<<endl;
			}
		}else{
			if(strcmp(b,"0")==0)
			{
				for(int i=0;i<n;i++)
				{
					
					char p[N],q[N];
					strcpy(p,final);
					strcpy(q,a);
					bigmul(p,q,final);
				}
				cout<<final<<endl;
			}else{
				char aa[N];
				sprintf(aa,"%s%s",a,b);
				int len1=strlen(b)*n;
				for(int i=0;i<n;i++)
				{					
					char p[N],q[N];
					strcpy(p,final);
					strcpy(q,aa);
					bigmul(p,q,final);
				}
				int len2=strlen(final);
				for(int i=0;i<len2-len1;i++)
					printf("%c",final[i]);
				printf(".");
				for(int i=len2-len1;i<len2;i++)
					printf("%c",final[i]);
				printf("\n");
			}
		}					
	}
    return 0;
}

高精度的題還是需要細心細心在細心才能AC呀!