POJ_1001(Exponentiation) 求高精度幂 攻略中...

题目如下:

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. 

This problem requires that you write a program to compute the exact value of R n where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.


大数高精度计算,通常都是用字符串来存储数据的每一位,分而求之。

对于本题,我的想法是:



由于两个数相乘,其结果为一个因数的各个位分别乘以另一个因数的积之和。比如:

1314 × 520 可以视作:0 × 1314 + 20 × 1314 + 500 × 1314

=>   0 × 1314 × 1 + 2 × 1314 × 10 + 5 × 1314 × 100

我先编写了一个plus函数,用来计算两数相加的和。

在编写plus函数时,发现我们通常手算加法的时候,都是从低位开始相加,并且当同位上的两个数相加>=10的时候,要向较高位进1。但是,在程序中,若按一般的逻辑,我们会把较高位放在string(字符串)的开头(左边),较低位放在末尾(右边),这样的顺序会导致我们在计算过程中,加大了进位或其他操作的复杂度。而若是按相反的顺序来存放,计算就方便得多了。(如数字123,存储顺序为321)。

然后编写了multiply函数,在函数中调用plus,得出两个数的乘积。


然而,提交后发现这种方法效率过低,系统给了个Output Limit Exceeded

继续思考改进方法。。。


以下为代码(低效):

#include <iostream>
#include <string>
#include <iterator>
using namespace std;

void inverted_sequence(string& s)
{
	char temp;
	for (int i = 0, j = s.size() - 1; i < j; i++, j--)
	{
		temp = s[i];
		s[i] = s[j];
		s[j] = temp;
	}
}

void plus(string& out, string s1, string s2)
{
	int		i;
	string*	s;
	string	t = "";

	i = s1.size() - s2.size();
	if (i < 0)
	{
		i *= -1;
		s = &s1;
	}
	else s = &s2;
	for (; i > 0; i--)
		s->push_back('0');
	s1.push_back('0');
	s2.push_back('0');

	int a, b, sum;
	for (i = 0; i < (int)s1.size(); i++)
	{
		a = s1[i] - '0';
		b = s2[i] - '0';
		sum = a + b;
		if (sum >= 10)
		{
			t.push_back(sum % 10 + '0');

			for (int j = i + 1; j < (int)s1.size(); j++)
			{
				a = s1[j] - '0';
				a++;
				s1[j] = a % 10 + '0';
				if (a < 10) break;
			}
		}
		else t.push_back(sum + '0');
	}

	i = (int)t.size() - 1;
	if (t[i] == '0')
		t.erase(i, 1);

	out = t;
}

void multiply(string& out, string s1, string s2)
{
	int		n		=	(int)s1.size();
	int		m		=	(int)s2.size();
	string*	prdct	=	new string[n];
	string*	sum	=	new string[m];

	int	i, j, k;

	for (i = 0; i < n; i++)
		prdct[i] = "";
	for (i = 0; i < m; i++)
		sum[i] = "0";

	int a, b, r;
	for (i = 0; i < m; i++)
	{
		b = s2[i] - '0';
		for (j = 0; j < n; j++)
		{
			a = s1[j] - '0';
			r = a * b;

			for (k = 0; k < j; k++)
				prdct[j] = prdct[j] + "0";
			for (k = 1; r / k >= 1; k *= 10)
				prdct[j].push_back(r / k % 10 + '0');
		}

		for (j = 0; j < n; j++)
		{
			plus(sum[i], sum[i], prdct[j]);
			prdct[j] = "";
		}

		for (k = 0; k < i; k++)
			sum[i].insert(0, "0");
	}

	out = "0";
	for (i = 0; i < m; i++)
		plus(out, out, sum[i]);

	delete [] prdct;
	delete [] sum;
}

void initialize(string& s, const int n, int& pn)
{
	string::iterator iter;

	iter = s.begin();

	while (iter != s.end() && *iter == '0')
		++iter;
	if (iter != s.begin())
		s.erase(s.begin(), iter);

	inverted_sequence(s);

	iter = s.begin();

	while (iter != s.end() && *iter == '0')
		++iter;
	if (iter != s.begin())
		s.erase(s.begin(), iter);

	for (int i = 0, size = (int)s.size(); i < size; i++)
	{
		if (s[i] == '.')
		{
			pn = i;
			break;
		}
	}
	if (pn)
	{
		s.erase(pn, 1);
		pn *= n;
	}
	else
		pn = -1;
}

void exponentiation(string& out, string& base_number, int n)
{
	string	square;
	string	prdct	= "1";
	int		pn		= 0;
	int		m		= n;

	initialize(base_number, n, pn);

	if(base_number == "")
	{
		out = "0";
		return;
	}
	if(n == 0)
	{
		out = "1";
		return;
	}

	multiply(square, base_number, base_number);
	for(int i = 0; i < m / 2; i++)
	{
		multiply(prdct, square, prdct);
	}
	if (n % 2)
		multiply(prdct, prdct, base_number);

	while ((int)prdct.size() < pn)
		prdct.push_back('0');
	if(pn >= 0)
		prdct.insert(pn, ".");
	inverted_sequence(prdct);

	out = prdct;
}
int main(void)
{
	string	s;
	int		n = 0;

	while(n != -1)
	{
		cin >> s >> n;

		exponentiation(s, s, n);

		cout << s << endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25. 输入说明 The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9. 输出说明 The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer. 输入样例 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 小提示 If you don't know how to determine wheather encounted the end of input: s is a string and n is an integer C++ while(cin>>s>>n) { ... } c while(scanf("%s%d",s,&n)==2) //to see if the scanf read in as many items as you want /*while(scanf(%s%d",s,&n)!=EOF) //this also work */ { ... } 来源 East Central North America 1988 北大OJ平台(代理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值