终于有时间来练习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;
}