20240321每日一题题解

折柳 / 2024-03-21 / 原文

20240321每日一题题解

Problem

已知 \(f(x,n)=\sqrt{n+\sqrt{(n-1)+\sqrt{(n-2)+\sqrt{...+2+\sqrt{1+x}}}}}\)

计算 \(f\) 的值。

输入 \(x\)\(n\)​。输出这个函数值,并且注意需要保留两位小数。

例如,输入4.2 10,则应该输出3.68

Solution

递归?循环?

说实话这道题是有一定思考量的,初看可能会无从下手。

\[\begin{aligned} & f(x, 1)=\sqrt{1+x} \\ & f(x, 2)=\sqrt{2+\sqrt{1+x}}=\sqrt{2+f(x, 1)} \\ & f(x, 3)=\sqrt{3+\sqrt{2+\sqrt{1+x}}}=\sqrt{3+f(x, 2)}=\sqrt{3+\sqrt{2+f(x, 1)}} \\ & ... \end{aligned} \]

可以得出普遍结论:

\[f(x,n)=\sqrt{n+f(x,n-1)} \]

如此,就可以依照我们昨天的递归来解决了。


当然,也可以用循环解决这道题。

我们从内部向外剖析:

\[f(x,n)=\sqrt{n+\sqrt{(n-1)+\sqrt{(n-2)+\sqrt{...+2+\sqrt{1+x}}}}} \]

这个函数的最内层是\(\sqrt{1+x}\),而后再给\(\sqrt{1+x}\)加上了\(2\),再套了根号;再加上了\(3\),再套了根号;再加上了\(4\),再套了根号;……;再加上了\((n-1)\),再套了根号;再加上了\(n\)​,再套了根号。

所以可以用写成for循环的格式,每次给答案执行+i再套根号,边界是i<=n

保留两位小数

c++中有两种保留两位小数的方法,分别是给coutprintf使用的。

虽然老师上课说printfc的,其实c++中依然可以使用printf,其在头文件cstdio当中,完完全全可以正常使用。我认为其也是c++不可或缺的一部分。

cout

默认情况下,cout使用 6 个有效数显示浮点值,其余自动四舍五入,有后缀0则会自动舍去。

使用 cout<<fixed<<setprecision(2)来控制接下来输出的小数位数,括号里是几就保留几位小数。

这个函数在头文件#include<iomanip>中。

printf

这个可以类比python中的%格式符:

printf("%.2lf\n",f(x,n));表示保留小数点后两位。

Code

递归写法

#include<iostream>
#include<cmath>//使用sqrt
#include<iomanip>//cout的setprecision控制小数位数
#include<cstdio>//使用printf
using namespace std;

double f(double x,int n)
{
	if(n==1)
	{
		return sqrt(1+x);
	}
	return sqrt(n+f(x,n-1));
}

int main()
{
	double x;
	int n;
	cin>>x>>n;
	cout<<fixed<<setprecision(2)<<f(x,n)<<endl;
//	printf("%.2lf\n",f(x,n));
	return 0;
}

循环写法

#include<iostream>
#include<cmath>//使用sqrt
#include<iomanip>//cout的setprecision控制小数位数
#include<cstdio>//使用printf
using namespace std;

int main()
{
	double x;
	int n;
	cin>>x>>n;
	double ans=x;
	for(int i=1;i<=n;i++)
	{
		ans=sqrt(i+ans);
	}
	
	cout<<fixed<<setprecision(2)<<ans<<endl;
//	printf("%.2lf\n",f(x,n));
	return 0;
}

AC