调和级数求和(打表/欧拉常数) - Harmonic Number LightOJ - 1234

调和级数求和(打表/欧拉常数) - Harmonic Number LightOJ - 1234

题意:

计 算 调 和 级 数 前 n 项 的 和 : 计算调和级数前n项的和: n:

H n = 1 + 1 2 + 1 3 + . . . + 1 n = ∑ i = 1 n 1 i H_n=1+\frac{1}{2}+\frac{1}{3}+...+\frac{1}{n}=\sum_{i=1}^n\frac{1}{i} Hn=1+21+31+...+n1=i=1ni1

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 108).

Output

For each case, print the case number and the nth harmonic number H n H_n Hn. Errors less than 10-8 will be ignored.

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

T i m e   l i m i t : 3000 m s , M e m o r y   l i m i t : 32768 k B Time\ limit:3000 ms,Memory \ limit:32768 kB Time limit3000msMemory limit32768kB


分析:

方法一:打表

考 虑 到 空 间 限 制 , 1 0 8 组 数 据 不 能 够 全 部 打 出 来 , 考虑到空间限制,10^8组数据不能够全部打出来, 108

但 可 以 每 隔 50 组 数 据 记 录 一 次 , 存 储 2 × 1 0 6 组 数 据 , 对 于 每 一 个 n , 再 做 一 个 50 次 以 内 的 递 推 。 但可以每隔50组数据记录一次,存储2×10^6组数据,对于每一个n,再做一个50次以内的递推。 502×106n50

方法二:欧拉常数

欧 拉 常 数 : 是 一 个 主 要 应 用 于 数 论 的 数 学 常 数 。 它 的 定 义 是 调 和 级 数 与 自 然 对 数 的 差 值 的 极 限 。 欧拉常数:是一个主要应用于数论的数学常数。它的定义是调和级数与自然对数的差值的极限。

在这里插入图片描述

γ ≈ 0.57721566490153286060651209 。 γ≈0.57721566490153286060651209。 γ0.57721566490153286060651209

渐进展开: γ = H n − l n   n − 1 2 n + 1 12 n 2 − 1 120 n 4 + . . . γ=H_n-ln\ n-\frac{1}{2n}+\frac{1}{12n^2}-\frac{1}{120n^4}+... γ=Hnln n2n1+12n21120n41+...

故 当 n 较 大 时 , 我 们 可 近 似 计 算 H n = l n   n + 1 2 n + γ 故当n较大时,我们可近似计算H_n=ln\ n+\frac{1}{2n}+γ nHn=ln n+2n1+γ

由 于 本 题 误 差 在 1 0 8 数 量 级 , 故 当 n < 10000 时 , 我 们 递 推 计 算 ; 否 则 我 们 直 接 套 公 式 计 算 。 由于本题误差在10^8数量级,故当n<10000时,我们递推计算;否则我们直接套公式计算。 108n<10000

法一代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

const int N=2e6+10;

double H[N];
int idx;

void Init()
{
    double tmp=0;
    for(int i=1;i<=1e8;i++)
    {
        tmp+=1.0/i;
        if(i%50==0) H[++idx]=tmp;
    }
}

int main()     
{
    Init();
    
    int T; cin>>T;
    for(int t=1;t<=T;t++)
    {
        int n; scanf("%d",&n);
        int s=n/50;
        double d=0;
        for(int i=s*50+1;i<=n;i++) d+=1.0/i;
        printf("Case %d: %.8lf\n",t,H[s]+d);
    }

    return 0;
}

法二代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

#define ll long long

using namespace std;

const int N=1e4+10;
const double C=0.57721566490153286060651209;

double H[N];

void Init()
{
    for(int i=1;i<=1e4;i++) H[i]=H[i-1]+1.0/i;
}

int main()     
{
    Init();
    
    int T; cin>>T;
    for(int t=1;t<=T;t++)
    {
        int n; scanf("%d",&n);
        double ans;
        if(n<10000) ans=H[n];
        else ans=log(n)+1.0/(2*n)+C;
        
        printf("Case %d: %.8lf\n",t,ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值