题目大意:
调和级数求和,即:
ans=∑i=1n1i
思路:
分段打标
分别求出 1∼100,101∼200,…1e8100−99∼1e8100 的表;求和;
公式
ans=log(n)∗log(n+1)2+Er;(n≥100000,Er=0.57721566490153286060651209)
//打表
#include <iostream>
#include <cstdio>
#define N 100000000
using namespace std;
double a[N /100 + 5];
void init()
{
a[0] = 0;
a[1] = 1;
double t = 1.0;
for (int i = 2; i <= N; i++)
{
t = t + 1.0 / i;
if (i % 100 == 0)
{
a[i /100] = t;
}
}
}
int main()
{
init();
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++)
{
int n;
scanf("%d", &n);
int t = n / 100;
double sum = a[t];
for (int i = t * 100 + 1; i <= n; i++)
{
sum += 1.0 / i;
}
printf("Case %d: %.10lf\n", cas, sum);
}
return 0;
}
//公式
#include <iostream>
#include <cstdio>
#include <cmath>
#define ER 0.57721566490153286060651209
using namespace std;
double fn[100005];
void init()
{
fn[0] = 0;
fn[1] = 1;
for (int i = 2; i <= 100000; i++)
{
fn[i] = fn[i - 1] + 1.0 / i;
}
}
double find(int n)
{
return ER + (log(n) + log(n + 1)) / 2;
}
int main()
{
init();
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++)
{
int n;
scanf("%d", &n);
printf("Case %d: ", cas);
if (n <= 100000)
{
printf("%.10lf\n", fn[n]);
}
else
{
printf("%.10lf\n", find(n));
}
}
return 0;
}