题目链接:https://cn.vjudge.net/contest/318269#problem/F
Sample Input
12
1
2
3
4
5
6
7
8
9
90000000
99999999
100000000
Sample Output
Case 1: 1
Case 2: 1.5
Case 3: 1.8333333333
Case 4: 2.0833333333
Case 5: 2.2833333333
Case 6: 2.450
Case 7: 2.5928571429
Case 8: 2.7178571429
Case 9: 2.8289682540
Case 10: 18.8925358988
Case 11: 18.9978964039
Case 12: 18.9978964139
翻译:给你一个n,求f(n)=1/1+1/2+…+1/n;(即求n的调和级数)
分析: n (1 ≤ n ≤ 108),打表会超时。
1.用欧拉公式求:
调和级数(即f(n))至今没有一个完全正确的公式,但欧拉给出过一个近似公式:(n很大时)
f(n)≈ln(n)+C+1/2*n
欧拉常数值:C≈0.57721566490153286060651209
c++ math库中,log即为ln。
注:n很小时直接求,此时公式不是很准。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define C 0.57721566490153286060651209
#define N 10000
double a[N];
int n;
void solve()
{
a[1]=1;
for(int i=2; i<N; i++)
a[i]=a[i-1]+1.0/i;
}
int main()
{
int T,k=1;
scanf("%d",&T);
solve();
while(T--)
{
scanf("%d",&n);
if(n<N)
{
printf("Case %d: %.10lf\n",k++,a[n]);
continue;
}
double x=log(n)+C+1.0/(2*n);
printf("Case %d: %.10lf\n",k++,x);
}
return 0;
}
2.打表水过(每40个数记录一次结果)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100000001
double a[2500001]={0.0,1.0};
void solve()
{
memset(a,0,sizeof(a));
double s=1.0;
for(int i=2; i<N; i++)
{
s+=(1.0/i);
if(i%40==0)/*每40个数记录一次结果*/
a[i/40]=s;
}
}
int main()
{
int T,f=1;
scanf("%d",&T);
solve();
while(T--)
{
int n;
scanf("%d",&n);
printf("Case %d: ",f++);
int x=n/40;
double sum=a[x];
for(int i=40*x+1;i<=n;i++)
sum+=(1.0/i);
printf("%.10lf\n",sum);
}
return 0;
}