题面
题目描述
已知:$$ S_n=1+frac{1}{2}+ frac{1}{3}+cdots+frac{1}{n} $$ 显然对于任意一个整数(K),当(n)足够大的时候,(S_n)大于(K)。
现给出一个整数(K)((1 le k le 15)),要求计算出一个最小的(n);使得(S_n>K)。
输入格式
一个正整数(K)
输出格式
一个正整数(N)
输入输出样例
输入 #1
1
输出 #1
2
正解做法
正解做法的话就是纯模拟啦,这个我就不阐述了。
#include <iostream>
#include <cstdio>
using namespace std;
int k,i;
int main()
{
double s=0.000000;
scanf("%d",&k);
do
{
i++;
s=s+(1.0/i);
}while(s<=k);
printf("%d
",i);
return 0;
}
一点也不温馨的提示:注意精度问题。
非正规做法
首先来看一下数据范围:
@> 1<=k<=15
数据范围如此之低,我们就能很自然地想到打表了。
所以本篇题解更准确的来说是一个打表教程。
好开始
Step One
首先魔改一下程序,变成这样:
#include <iostream>
#include <cstdio>
using namespace std;
int k,i;
int main()
{
freopen("C:/Users/we/Desktop/p1035_data.out","w",stdout);
double s=0.000000;
for(int k=1;k<=15;k++)
{
s=0.000000;
i=0;
do
{
i++;
s=s+(1.0/i);
}while(s<=k);
printf(" if(k==%d) return %d;
",k,i);
}
return 0;
}
这其实就是打表的generator
啦~
为什么要这么打?还把if
啥写上了?
当然是因为懒方便啦~
同时你又看到了制表符?
当然是因为懒美观啦~
运行程序,效果如下:
Step Two
把这段复制下来,再魔改一通,就是这样:
#include <iostream>
#include <cstdio>
using namespace std;
int k;
int work()
{
if(k==1) return 2;
if(k==2) return 4;
if(k==3) return 11;
if(k==4) return 31;
if(k==5) return 83;
if(k==6) return 227;
if(k==7) return 616;
if(k==8) return 1674;
if(k==9) return 4550;
if(k==10) return 12367;
if(k==11) return 33617;
if(k==12) return 91380;
if(k==13) return 248397;
if(k==14) return 675214;
if(k==15) return 1835421;
}
int main()
{
scanf("%d",&k);
printf("%d
",work());
return 0;
}