题目传送门:https://vjudge.net/problem/LightOJ-1234
方法一:(有点投机取巧了)
公式如下:
其中r为常数,r=0.57721566490153286060651209(r就是欧拉常数)
but n大的时候,精确度才高。所以数小的时候就打表。
特别注意,由于题目要求精度为10^-8,常数r为有限位数,所以正常利用这个公式,并不能达到精度要求。经尝试,在原公式的基础上,再减去一个1.0/(2*n)恰好可以满足精度。((⊙o⊙)…好像比赛的话,要gg)
ac代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define N 200005
#define ll long long
using namespace std;
#define R 0.57721566490153286060651209
double ans[10010];
int main()
{
int t,n,casenum=0;
double sum;
ans[1]=1;
for(int i=2; i<=10000; i++)
{
ans[i]=ans[i-1]+1.0/i;
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n<=10000)
{
printf("Case %d: ",++casenum);
printf("%.10lf\n",ans[n]);
}
else
{
sum=log(n+1)+R-1.0/(2*n);
printf("Case %d: ",++casenum);
printf("%.10lf\n",sum);
}
}
return 0;
}
但是,题目主要考查一种打表和地腿的方法。没50个为一组,这样打表我们接受,然后在进行递推。
ac代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define N 100000000
#define ll long long
using namespace std;
double ans[2000100];
int main()
{
int t,n,cas = 1, k = 1;
double sum = 1;
ans[0] = 0.0;
for(int i = 2; i <= N; i++)
{
sum = sum + 1.0 / i;
if(i%50 == 0)
ans[k++] = sum;
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int shu = n / 50;
double num = ans[shu];
for(int i = 50 * shu + 1; i <= n; i++)
{
num += 1.0 / i;
}
printf("Case %d: %.10lf\n", cas++, num);
}
return 0;
}