一、问题介绍
[NOIP2002 普及组] 级数求和
题目描述
已知: S n = 1 + 1 2 + 1 3 + … + 1 n S_n= 1+\frac{1}{2}+\frac{1}{3}+…+\frac{1}{n} Sn=1+21+31+…+n1。显然对于任意一个整数 k k k,当 n n n 足够大的时候, S n > k S_n>k Sn>k。
现给出一个整数 k k k,要求计算出一个最小的 n n n,使得 S n > k S_n>k Sn>k。
输入格式
一个正整数 k k k。
输出格式
一个正整数 n n n。
样例 #1
样例输入 #1
1
样例输出 #1
2
提示
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ k ≤ 15 1\le k \le 15 1≤k≤15。
【题目来源】
NOIP 2002 普及组第一题
二、错误做法回顾
#include <iostream>
using namespace std;
double func(int n)
{
double sum=0;
for (int i = 1; i <= n; ++i) {
sum += 1/double(i);
}
return sum;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int k,n=1;
cin>>k;
while (func(n)<=k)
{
n++;
}
cout<<n;
}
当时做的时候大脑可能有点抽,还想着为了好看去定义一个函数方便我们去求给定输入n时,
从1到n的级数,光看这一点是没有问题的,但问题就在于我在main函数当中写的while循环,
每一次while循环又都去再来一个n循环去求级数,时间复杂度已经远超O(n2)了。
三、正确做法
正确的做法其实很简单!我们只用想办法只求一次输入级数的和即可,所以只用在main函数当中while循环里面求就可以了,想循环到哪就加到哪一步。
#include <iostream>
using namespace std;
int main()
{
int k,i=1;
double sum=0;
cin>>k;
while(sum<=k)
{
sum += 1/double(i);
i++;
}
cout<<i-1;
}
四、反思与总结
由于自己平时刷题比较少,因此当遇到这类问题的时候缺乏相关的经验,不要老想着为了让代码整体看起来更具有层次性就去做很多无意义的工作,有时候可能题目本身很简单,但我们的代码将其复杂化了!