求幂

74 篇文章 0 订阅

求幂

时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:390            测试通过:98

描述

Rn次幂(0.0<r<99.999,0<n<=25)

输入

每行输入两个数Rn

R值占1-6列,n8-9

输出

对应于每一行输入,输出Rn次幂

前导的0不要输出

无意义的0不要输出

如果结果是一个整数,不要输出小数点

最后一行是空行

样例输入

95.123 12
0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12

样例输出

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

题目来源

POJ


分析:

大数运算,涉及小数点和0的问题,有些复杂。

老方法输入字符串转化成int型数组,这里r是6位的,n不重要,因为空格结束,所以用循环

while(scanf("%s %d",&s,&n) != EOF) 
将6位的char型数组转换成int型数组,注意:数组开6位出错,因为还有一个结束符,索性直接开10。为了输出考虑,记录小数点后面的数的个数point。

考虑到大数相乘时数组下标从0开始,将int型数组逆序。

之后大数相乘,将int数组a拷贝到int数组b,方便传递参数。(写法有很多,感觉写的好烦)num为一开始输入的字符串里数字的个数,不包括0.0001中前面无意义的0,每次乘以b数组,数组的个数num <= num+6,因为b数组长度小于6 。

大数相乘:

void fun(int a[], int b[], int num)
{
	int mul[10000] = {0};
	for(int i=0;i<num;i++)
		for(int j=0;j<5;j++)
			mul[i+j] += a[i] * b[j];
	for(int i=0;i<num+6;i++) // +6 足矣
	{
		mul[i+1] += mul[i] / 10;
		mul[i] = mul[i] % 10;
	}
	for(int i=0;i<num+6;i++) // 再赋予a
		a[i] = mul[i];
}
每次乘完一个b数组,将得到的乘积数组再返回给a,循环n-1次。最后得到的最终数组是逆序的,且前后有一些无效的0。

Eg:95.123 12 得到的为:12725896912276............................651884500000000000

要输出的是:548815620517731830194541.899025343415715973535967221869852721

只要输入的小数点后面不是1.1100这种情况,首位一定非0。


最重要的是输出。

小数点后的位数为point*n,还有一种特殊情况:小数点后位数中有无效的0。原因是1.1100记录的point为4,则point*n=4n,但是其实只要输出2n,因为后面的0无效。

for(i=num-1;i>=0;i--) 
			if(a[i]!=0) break;
此时i为总的数字的位数。

if(point>i) // .xxxxx
		{
			printf("."); // 全在小数点右边
			//
			for(tmp=0;tmp<num;tmp++) // 右边多余的0不输出
				if(a[tmp]!=0) break;
			//
			for(int k=point-1;k>=tmp;k--) // 逆序输出
			{
				printf("%d",a[k]);
			}
		}
else // xxxx.xxxx 或者 xxxx
		{
			for(;i>point-1;i--) // 打印小数点左边的数 条件 i>point-1 保证小数point个
			{
				printf("%d",a[i]);
			}
			//
			for(tmp=0;tmp<num;tmp++) // 小数点右边第一个非0的下标 tmp
				if(a[tmp]!=0) break;
			//
			if(i>=tmp) // 存在小数
				printf(".");            
			for(;i>=tmp;i--)
				printf("%d",a[i]);
		}

完整代码:

#include<stdio.h>

//求幂

void fun(int a[], int b[], int num)
{
	int mul[10000] = {0};
	for(int i=0;i<num;i++)
		for(int j=0;j<5;j++)
			mul[i+j] += a[i] * b[j];
	for(int i=0;i<num+6;i++) // +6 足矣
	{
		mul[i+1] += mul[i] / 10;
		mul[i] = mul[i] % 10;
	}
	for(int i=0;i<num+6;i++) // 再赋予a
		a[i] = mul[i];
}
int main()
{
	char s[10];
	int n;
	while(scanf("%s %d",&s,&n) != EOF) 
	//while(cin>>s>>n)
	{
		int a[10000] = {0};
		int num= 0,point;

		for(int i=0;i<6;i++)
		{
			if(num == 0 && s[i] == '0') // 首位为0
			{
				continue;
			}
			if(s[i] != '.')
				a[num ++] = s[i] - '0';  // m.数字 != 0
			if(s[i] == '.')
				point = 5 - i; // 小数点后面几位 1.0100 
		}

		//逆序
		for(int i=0;i<num/2;i++)
		{	
			int tmp = a[i];
			a[i] = a[num - i - 1];
			a[num -i -1] = tmp;
		}
		//start!
		//拷贝数组a到数组b,作乘数
		int b[5];
		for(int i=0;i<5;i++)
			b[i] = a[i];
                //循环求幂
		for(int i=0;i<n-1;i++)
		{
			fun(a, b, num);
			num = num + 6;
		}
		
		//输出重点! 依据小数点后数的个数
		point = point * n; // 小数点后面几位
		int i,tmp;
		for(i=num-1;i>=0;i--) // num-1 ~ 0; 第一个非0的是先输出的(1.23456 中的1)
			if(a[i]!=0) break;
		if(point>i) // .xxxxx
		{
			printf(".");
			//
			for(tmp=0;tmp<num;tmp++)
				if(a[tmp]!=0) break;
			//
			for(int k=point-1;k>=tmp;k--) // 逆序输出
			{
				printf("%d",a[k]);
			}
		}
		else // xxxx.xxxx or xxxx
		{
			for(;i>point-1;i--) // 打印小数点左边的数 条件 i>point-1 保证小数point个
			{
				printf("%d",a[i]);
			}
			//
			for(tmp=0;tmp<num;tmp++) // 多余的0无需输出
				if(a[tmp]!=0) break;
			//
			if(i>=tmp) // 存在小数
				printf(".");            
			for(;i>=tmp;i--)
				printf("%d",a[i]);
		}
		printf("\n");
	}
	return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值