题目不难, 高精度求幂=矩阵快速幂+高精度乘法运算
给定一个浮点数r和整数n,要求出r^n。很明显就是矩阵快速幂,但是由于要求精度极高,故需要高精度的乘法运算。
具体思路如下:
首先将浮点数转化为整数,然后就是整数求幂了。但由于数据量极大,故要采用高精度乘法。最后将得到的整数结果返回小数结果
解题时注意这几点:
1)前导0和尾部0都不能存在
2)当结果转化后为纯小数时,注意小数点前的0不要存在
3)注意整数结果转化为最终结果时,小数点的位置和加0关系
4)乘法的高精度运算后结果要返回原数组,并注意长度的变化
下面是代码:168K+0MS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 1010
#define Maxx 1100
char Input[Maxx]; //输入浮点数字符串
int trans[Max]; //浮点数转化为整数数组
int result[Max]; //存储整数幂运算结果
int mid[Max]; //高精度乘法运算中间辅助数组
int n,num,back; // 幂、浮点数转化为整数时需要*10^num,back为整数幂运算结果转化为浮点数最终结果需要加 除以 10^back (back=num*n)
int len_trans,len_result; // 中间数组长度,结果数组长度
void exp1(){ //高精度乘法运算,result*trans
int i,j;
memset(mid,0,sizeof(mid)); //初始化为全0
for(i=0;i<len_result;i++) //高精度乘法运算核心
for(j=0;j<len_trans;j++)
mid[i+j]+=result[i]*trans[j];
for(i=0;i<Max;i++) //转化为十进制
if(mid[i]>=10){
mid[i+1]+=mid[i]/10;
mid[i]%=10;
}
for(i=Max-1;i>=0;i--) //去除前导0
if(mid[i]>0)
break;
for(j=i;j>=0;j--) // 状态回归
result[j]=mid[j];
len_result=i+1; // 注意长度
}
void exp2(){ // 高精度乘法运算,trans*trans
memset(mid,0,sizeof(mid)); //初始化为全0
int i,j;
for(i=0;i<len_trans;i++) //高精度乘法核心
for(j=0;j<len_trans;j++)
mid[i+j]+=trans[i]*trans[j];
for(i=0;i<Max;i++) //转化为十进制
if(mid[i]>=10){
mid[i+1]+=mid[i]/10;
mid[i]%=10;
}
for(i=Max-1;i>=0;i--) //去除前导0
if(mid[i]>0)
break;
for(j=i;j>=0;j--) //状态回归
trans[j]=mid[j];
len_trans=i+1; //注意长度
}
void epo(){ // 矩阵快速幂
while(n>0){ // 矩阵快速幂算法核心
if(n&1)
exp1(); //result*trans
exp2(); // trans*trans
n>>=1; //进一位
}
if(back>=len_result){ // 若最终结果小数点位置大于等于整数长度,则为纯小数
printf("."); //注意不要输出小数点前的0
for(int i=back-1;i>=len_result;i--) // 加0
printf("0");
int i;
for(i=0;i<=len_result-1;i++) // 尾部0去掉
if(result[i]>0)
break;
for(int j=len_result-1;j>=i;j--) // 中间不是0的数字
printf("%d",result[j]);
}
else{ //不是纯小数
for(int i=len_result-1;i>=back;i--) //输出整数部分
printf("%d",result[i]);
int i;
for(i=0;i<=len_result-1;i++) // 去除尾部0
if(result[i]>0)
break;
if(back-1>=i){ // 若不是整数,则要输出小数点
printf(".");
for(int j=back-1;j>=i;j--)
printf("%d",result[j]);
}
}
printf("\n"); //空格
}
int main(){
while(scanf("%s%d",Input,&n)!=EOF){ // 输入浮点数和整数幂
int len=strlen(Input); // 浮点数初始长度
int pivot=1,Sum=0; // 初始化十进制个位为1,十进制数为0
int snum=0; // 初始化为0,转化为整数需要乘以*10^snum
bool trag=true;
for(int i=len-1;i>=0;i--){ // 从浮点数最右边开始
if(trag && Input[i]=='0') // 若为0则继续试探
continue;
else if(trag && Input[i]!='0' && Input[i]!='.'){ //若小数部分第一个不为0的数字出现
snum++; //开始计数
trag=false; //转换标记
Sum+=(Input[i]-'0')*pivot; // 开始转化为整数
pivot*=10; // 乘以10
}
else if(!trag && Input[i]!='.'){ // 处理小数部分后第一个不为0的数字出现后
snum++;
Sum+=(Input[i]-'0')*pivot;
pivot*=10;
}
else if(Input[i]=='.'){ //小数点为分界点,接着处理整数部分
num=snum; // 结束计数
trag=false;//防止小数部分全0情况,则要转换标记
}
}
back=n*num; //转化结果需要 除以10^back
pivot=0;
while(Sum>0){ //将整数转化为整数数组
trans[pivot++]=Sum%10;
Sum/=10;
}
len_trans=pivot; // 长度
len_result=1; //初始化结果长度为1
result[0]=1; //初始话结果为1
epo();//处理矩阵快速幂
}
return 0;
}