poj1001

题目不难, 高精度求幂=矩阵快速幂+高精度乘法运算

给定一个浮点数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;
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值