题目描述
思路:
这道题是求高精度幂的结果,而不可能直接使用pow()函数,因为最后的结果太长了,需要使用数组来存储数据,所以必须改为使用大整数的运算,而这里主要算法是连续使用大整数乘法。大整数乘法核心算法如下:
c1[i+j]+=a[i]*b[j];
if (c1[i+j]>=10){
c1[i+j+1]+=c1[i+j]/10;
c1[i+j]%=10;
}
其中a[i],b[i]为逆序的两个数,就是如果123×456,则a[]={3,2,1},b[]={654},当然结果也是逆序的,输出的时候需要转回来。这段代码其实是模拟真实的乘法运算,效率不高,而大整数乘法可以用分治法进行优化将时间复杂度由O(n^2)降低为O(nlogn)。对于题目中小数点的处理,其实只需要将这个实数视为整数就行了,乘出来结果的小数点位置用类似科学计数法的处理就行了,比如123.456×789.123看做(123456×10^-3)×(789123×10^-3)=(123456×789123×10^-6),最后将小数点放在从后往左第6位就可以了,这个算法便是这道题的核心。
需要注意的是最后的输出,格式控制比较蛋疼,我错很多次就因为格式控制不正确。
代码:
#include <iostream>
using namespace std;
int main()
{
int array[100]={0};
char ch;
int i=0,j=0,k=0;
int deg,dotPos;
int n,finaldotPos;
char s[100];
while (cin>>s>>n)
{
memset(array,0,sizeof(array));
i=j=k=0;
deg=dotPos=finaldotPos=0;
while (i<strlen(s)){
ch=s[i++];
if(ch!='.')
deg=i-1,array[j++]=atoi(&ch);
else{
dotPos=i-1;
continue;
}
}
if (dotPos==0){
deg++;
finaldotPos=0;
}
else
finaldotPos=(deg-dotPos)*n;
int c1[500]={0},temp[500];//存储乘法计算结果
int r=0,len=deg;
for (k=0;k<deg;++k)
temp[k]=array[k];
for (r=0;r<n-1;++r){//高精度幂计算,大整数乘法
for (i=0;i<len;++i)
for(j=0;j<deg;++j){
c1[i+j]+=temp[len-1-i]*array[deg-1-j];
if (c1[i+j]>=10){
c1[i+j+1]+=c1[i+j]/10;
c1[i+j]%=10;
}
}
len+=deg;
for (k=0;k<len;++k){
temp[k]=c1[len-1-k];
c1[len-1-k]=0;
}
}
int intflag=0;
for (k=0;k<len-finaldotPos;++k){
if (temp[k]==0&&intflag==0)
continue;
else if(temp[k]!=0&&intflag==0){
intflag=1;
cout<<temp[k];
continue;
}
if(intflag==1){
cout<<temp[k];
}
}//输出整数部分
int dotflag=0;
int dottemp[100];
int nonzeronum;
i=0;
for (k=len-1;k>=len-finaldotPos;--k){
if (temp[k]==0&&dotflag==0)
continue;
else if (temp[k]!=0&&dotflag==0){
dotflag=1;
cout<<".";//输出小数点
dottemp[i++]=temp[k];
continue;
}
if (dotflag==1)
dottemp[i++]=temp[k];
}//清除小数部分最后的0
nonzeronum=i;//输出小数部分
for(i=nonzeronum-1;i>=0;--i)
cout<<dottemp[i];
cout<<endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main()
{
int array[100]={0};
char ch;
int i=0,j=0,k=0;
int deg,dotPos;
int n,finaldotPos;
char s[100];
while (cin>>s>>n)
{
memset(array,0,sizeof(array));
i=j=k=0;
deg=dotPos=finaldotPos=0;
while (i<strlen(s)){
ch=s[i++];
if(ch!='.')
deg=i-1,array[j++]=atoi(&ch);
else{
dotPos=i-1;
continue;
}
}
if (dotPos==0){
deg++;
finaldotPos=0;
}
else
finaldotPos=(deg-dotPos)*n;
int c1[500]={0},temp[500];//存储乘法计算结果
int r=0,len=deg;
for (k=0;k<deg;++k)
temp[k]=array[k];
for (r=0;r<n-1;++r){//高精度幂计算,大整数乘法
for (i=0;i<len;++i)
for(j=0;j<deg;++j){
c1[i+j]+=temp[len-1-i]*array[deg-1-j];
if (c1[i+j]>=10){
c1[i+j+1]+=c1[i+j]/10;
c1[i+j]%=10;
}
}
len+=deg;
for (k=0;k<len;++k){
temp[k]=c1[len-1-k];
c1[len-1-k]=0;
}
}
int intflag=0;
for (k=0;k<len-finaldotPos;++k){
if (temp[k]==0&&intflag==0)
continue;
else if(temp[k]!=0&&intflag==0){
intflag=1;
cout<<temp[k];
continue;
}
if(intflag==1){
cout<<temp[k];
}
}//输出整数部分
int dotflag=0;
int dottemp[100];
int nonzeronum;
i=0;
for (k=len-1;k>=len-finaldotPos;--k){
if (temp[k]==0&&dotflag==0)
continue;
else if (temp[k]!=0&&dotflag==0){
dotflag=1;
cout<<".";//输出小数点
dottemp[i++]=temp[k];
continue;
}
if (dotflag==1)
dottemp[i++]=temp[k];
}//清除小数部分最后的0
nonzeronum=i;//输出小数部分
for(i=nonzeronum-1;i>=0;--i)
cout<<dottemp[i];
cout<<endl;
}
return 0;
}
WA原因:
1.没有考虑到这种情况:输入10.00 2,应该输出100,而不是100.
2.最后输出结果之后没有cout<<endl,导致第二次输入数据时不能得出正确结果
3.没有考虑到最后计算结果精度,最开始声明的结果保存数组temp[100],最后改为temp[500],才保证了最后计算结果的准确性。