2013年第四届蓝桥杯C++B组省赛D题

2013年第四届蓝桥杯C++B组省赛D题

黄金连分数

黄金分割数0.61803… 是个无理数,这个常数十分重要,在许多工程问题中会出现。有时需要把这个数字求得很精确。

对于某些精密工程,常数的精度很重要。也许你听说过哈勃太空望远镜,它首次升空后就发现了一处人工加工错误,对那样一个庞然大物,其实只是镜面加工时有比头发丝还细许多倍的一处错误而已,却使它成了“近视眼”!!

言归正传,我们如何求得黄金分割数的尽可能精确的值呢?有许多方法。

比较简单的一种是用连分数:
1
这个连分数计算的“层数”越多,它的值越接近黄金分割数。

请你利用这一特性,求出黄金分割数的足够精确值,要求四舍五入到小数点后100位。

小数点后3位的值为:0.618
小数点后4位的值为:0.6180
小数点后5位的值为:0.61803
小数点后7位的值为:0.6180340
(注意尾部的0,不能忽略)

你的任务是:写出精确到小数点后100位精度的黄金分割值。

注意:尾数的四舍五入! 尾数是0也要保留!

显然答案是一个小数,其小数点后有100位数字,请通过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。

这个是fib的相邻比值。
不能用递归=-=会爆栈。
这个转化成fib的相邻比值。

分析的话可以根据式子。先把后面去掉。然后一项一项求。
比如枚举一下。
比值分别为1/1, 1/2, 2/3, 3/5, 5/8, 8/13…

很容易发现分母和分子的比值都是fib的数字=-=
第二点是保留到100位。应该对应到fib的哪一项才精确。
fib足够大的话已经不满足c的数据类型的要求。所以。
需要自己定义字符串来存储,以及写一套字符串的加法减法(除法可以转换位减法的)
用C语言的话。。。不在无比熟练的情况下,可能完成不了。
C++或者Java可以考虑一下
Java内部把什么什么的函数都已经跟你写好了。。
比较方便。。因为这是一道填空题。
这个地方用C++写。
加法,减法,除法。。。
这里的除法都可以转化为减法。
这个一个小tips:
不管加法还是减法。
在不知道位数的情况下
从低位开始加。直接反转就可以了从低位开始操作了。

除法转化为减法。这个地方是把fib的低位当作a,fib的高位当作b。
然后b一定大于a。
在做除法的过程中,模拟一下,所以给a在后缀直接加一个0.
直到a >= b为止。
然后开始逐层递减。
记录计算出来的小数位数。然后把它加到ans中就行~

append()是在字符串末尾追加
find_first_not_of()是指找到第一个不等于字符的位置。如果都符合就会返回string::npos
stringstream是串流
i2s代表把数字转化成字符串。stringstream这个东西还挺好用的
代码部分啦~

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

string add(string a, string b)
{
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	a.substr(a.find_first_not_of('0'));
	b.substr(a.find_first_not_of('0'));
	int lena = a.length();
	int lenb = b.length();
	int len = max(lena, lenb) + 10;
	
	string ans(len, '0');
	for (int i = 0; i < lena; i++)
	{
		ans[i] = a[i];
	} 
	int temp = 0;
	for (int i = 0; i < len; i++)
	{
		if (i < lenb)
		{
			temp += (ans[i] - '0') + (b[i] - '0');
		}
		else
		{
			temp += (ans[i] - '0');
		}
		ans[i] = (temp % 10) + '0';
		temp /= 10;
	}
	reverse(ans.begin(), ans.end());
	return ans.substr(ans.find_first_not_of('0'));
}

void i2s(int t, string &temp)
{
	stringstream ss;
	ss << t;
	ss >> temp;
}

int comp(string a, string b)
{
	if (a.length() > b.length())
	{
		return 1;
	}
	if (a.length() < b.length())
	{
		return -1;
	}
	else
	{
		if (a == b)
		{
			return 0;
		}
		else if (a > b)
		{
			return 1;
		} 
		else
		{
			return -1;
		}
	}
}

string substract(string a, string b)
{
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	for (int i = 0; i < b.length(); i++)
	{
		if (a[i] >= b[i])
		{
			a[i] = a[i] - b[i] + '0'; 
		}
		else
		{
			int k = 1;
			while (a[i + k] == '0')
			{
				a[i + k] = '9';
				k++;
			}
			a[i + k] = a[i + k] - '1' + '0';
			a[i] = (a[i] - b[i] + 10) + '0';
		}
	}
	reverse(a.begin(), a.end());
	if (a.find_first_not_of('0') == string::npos)
	{
		return "0";
	}
	return a.substr(a.find_first_not_of('0'));
}

string divide(string a, string b)
{
	string ans = "0.";
	int t;
	for (int i = 0; i < 101; i++)
	{
		a.append("0");
		t = 0;
		while (comp(a, b) >= 0)
		{
			a = substract(a, b);
			t++;
		}
		string temp;
		i2s(t, temp);
		ans.append(temp);
	}
	return ans;
}

int main()
{
	string a = "1";
	string b = "1";
	for (int i = 3; i < 101; i++)
	{
		string temp;
		temp = b;
		b = add(a, b);
		a = temp;
	}
	cout << divide(a, b) << endl;
	return 0;
}
发布了60 篇原创文章 · 获赞 2 · 访问量 1609

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/104714972