POJ 1001

终于有时间来练习POJ了。。。第一次写,花了好长时间。

题目大意:

这不用多说了,就是计算R^n次方。其中R在0.0到99.999之间,n在0到25之间。

-------------------------------------我是华丽的分割线--------------------------------------

这道题难点在于要求结果很精确。转换一下,就是大数求幂。所以呢,难点在于一个大数乘法,另一个在于分治法做阶乘。

大数乘法:字符串来做

分治法:递归

关于小数点的问题呢,因为主要是乘法,所以存储的时候直接表示成科学计数法就可以了,然后打印的时候再还原。

代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>          //第一次是CE,提示没有malloc.h,晕

typedef struct __data {
   char *data;
   int point;
   int len;
} da;

da *charTimes(da *a,da *b){              //乘法函数
	char *aChar=(a->data);
	char *bChar=(b->data);
	
	int aLen=a->len;
	int bLen=b->len;
	int ansLen=aLen+bLen;
	int ansPoint=a->point+b->point;
	
	da *ans=(da *)calloc(1,sizeof(da));
	char *ansChar=(char *)calloc(ansLen,sizeof(char));
	char *temp=(char *)malloc((bLen+1)*aLen*sizeof(char));
	
	int i,j;
	int sum;
	
	for (i=0;i<aLen;i++){      //首先是做各位数的乘法,竖式的中间结果保存在一个矩阵中
		 sum=0;
	   for (j=0;j<bLen;j++){
	   	 sum+=(bChar[j]-'0')*(aChar[i]-'0');
	     temp[i*(bLen+1)+j]=sum%10+'0';
	     sum=sum/10;
	   }
	   temp[i*(bLen+1)+j]=sum%10+'0';
	}
	
	sum=0;                        //竖式求和
	for (i=0;i<ansLen;i++){       //总是在各种限制的边界条件搞错,花费了很多时间,基本功不扎实啊!!
		 if (i-aLen+1>0){
		 	  j=i-aLen+1;
		 }
		 else j=0;
		 for (;((i-j)>=0)&&(j<=bLen);j++){
	     sum=sum+(temp[(i-j)*(bLen+1)+j]-'0');
	   }
	   ansChar[i]=sum%10+'0';
	   sum=sum/10;
	}

  free(temp);
  
  ans->data=ansChar;
  ans->point=ansPoint;
  ans->len=ansLen;
  return ans;
}

da *power_cal(da *a,int power){   //分治法幂递归
	da *ans;
	da *temp,*temp2;
	if (power==1){
		 da *ans=(da *)calloc(1,sizeof(da));
	   char *ansChar=(char *)calloc(a->len,sizeof(char));
	   ans->len=a->len;
	   ans->point=a->point;
	   ans->data=ansChar;
	   memcpy(ansChar,a->data,(a->len)*sizeof(char));
	   return ans;
	}
	else if (power==2){
	   return charTimes(a,a);
	}
	if (power%2==1){
		 temp=power_cal(a,power/2);
		 temp2=power_cal(temp,2);
		 ans=charTimes(temp2,a);
		 free(temp->data);
     free(temp);	
     free(temp2->data);
     free(temp2);		 
  }
  else {
  	 temp=power_cal(a,power/2);
		 ans=power_cal(temp,2);
		 free(temp->data);
     free(temp);		 
  }	
	return ans;
}

int printData(da *a){          //输出
	char *aChar=a->data;
	int i;
	int len=a->len;
	int subfix=0;
	int prefix=0;
	char *buffer;
	
	buffer=(char *)malloc((len+2)*sizeof(char));
	
	memcpy(buffer,aChar,a->point);
	buffer[a->point]='.';
	memcpy(&(buffer[a->point+1]),&(aChar[a->point]),len-(a->point));
	buffer[len+1]='\0';
	
	for (i=0;i<=len;i++){
	  if (buffer[i]!='0'){
	    break;
	  }
	}
	subfix=i;
	if (buffer[subfix]=='.'){     //第二次WA的时候没有考虑到整数的问题
		subfix++;
	}
	
	for (i=len;i>=0;i--){
	  if (buffer[i]!='0'){
	    break;
	  }
	}
	prefix=i;
	
	for (i=prefix;i>=subfix;i--){
    printf("%c",buffer[i]);
  }
  
  free(buffer);
  printf("\n");
}

int main(){
   char readTemp[20];
   int power;
   int aLen;
   int i;
   char *aChar;
   da *ans;
   da *a;
   
   while(scanf("%s %d",readTemp,&power)!=EOF){          
     aLen=strlen(readTemp);
     
     a=(da *)calloc(1,sizeof(da));
	   aChar=(char *)calloc(aLen,sizeof(char));
     
     a->point=0;                          //第二次WA的时候没有考虑到整数的问题
     for (i=0;i<aLen;i++){
     	  if (readTemp[aLen-i-1]=='.'){   	     
     	     a->point=i;
     	     i--;
     	     aLen=aLen-1;
     	  }
     	  else {
           aChar[i]=readTemp[aLen-i-1];
        }
     }
     
     a->data=aChar;
     a->len=aLen;
     
     ans=power_cal(a,power);
     
     printData(ans);
     
     free(ans->data);
     free(a->data);
     free(ans);
     free(a);
   }
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值