算法训练 调和数列问题

Description

  输入一个实数x,求最小的n使得,1/2+1/3+1/4+...+1/(n+1)>=x。
  输入的实数x保证大于等于0.01,小于等于5.20,并且恰好有两位小数。你的程序要能够处理多组数据,即不停地读入x,如果x不等于0.00,则计算答案,否则退出程序。
  输出格式为对于一个x,输出一行n card(s)。其中n表示要计算的答案。

Input

输入描述:
  分行输入x的具体数值
输入样例:

1.00
3.71
0.04
5.19
0.00

Output

输出描述:
  分行输出n的数值,格式为n card(s)
输出样例:

3 card(s)
61 card(s)
1 card(s)
273 card(s)

Hint

  HINT:时间限制:1.0s 内存限制:512.0MB

Source

  蓝桥杯练习系统 ID: 107 原题链接: http://lx.lanqiao.cn/problem.page?gpid=T107

Thought

  因为本题是多次输入求值,不是求一次的事情,所以考虑先生成一个调和数列,然后二分查找。
  学习使用两个库函数:lower_bound( ) 和 upper_bound( ) 

lower_bound( begin, end, num):二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin得到找到数字在数组中的下标。

upper_bound( begin, end, num):二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

lower_bound( begin, end, num, greater() ):二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater() ):二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

Submit

#include <iostream>
#include <map>
using namespace std;

int main() {
	map<double, int> sequence;  //前一个是n值下的和,后一个是n值 
	double s=0;
	for(int i=1; s<=5.20; i++) { //生成调和数列 
		s += 1.0/(i+1);
		sequence[s]=i;
	}
	
	double x;
	map<double, int>::iterator iter; 
	while(cin>>x, x!=0.00) { //先执行输入,再执行判断 
		iter = sequence.lower_bound(x);
		cout<< iter->second <<" card(s)"<<endl;
	}
	return 0;
}

posted on 2018-12-28 23:53  yejifeng  阅读(746)  评论(0)    收藏  举报

导航