This commit is contained in:
ljcjames 2022-08-18 10:53:07 +08:00
parent 9e1a6289e8
commit 7e74c42a6e
6 changed files with 167 additions and 9 deletions

View File

@ -46,7 +46,7 @@ int main()
{
ans+=(1.0/i);
}
printf("Case %d: %.10llf\n",++t1,ans);
printf("Case %d: %.10lf\n",++t1,ans);//WA罪魁祸首 lf->double 不是llf
}
return 0;
}

View File

@ -0,0 +1,40 @@
//调和级数近似公式f(n)=ln(n)+r+1.0/(2*n)
//r是欧拉常数
//注意此公式只适用于n很大的情况。
#include<cstdio>
#include<algorithm>
#include <cmath>
using namespace std;
#define r 0.57721566490153286060651209//欧拉常数
const int N=1e8;
const int w=1e4;
double a[w+5];
int t,n;
int t1;
double ans;
inline void cun()
{
for(int i=1;i<=w;i++)
{
a[i]=a[i-1]+(1.0/i);
}
}
int main()
{
cun();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n<=w)
{
printf("Case %d: %.10lf\n",++t1,a[n]);//lf->double 不是llf
}
else
{
ans=log(n)+r+1.0/(2*n);//cmath 中log就是ln
printf("Case %d: %.10lf\n",++t1,ans);
}
}
return 0;
}

View File

@ -0,0 +1,34 @@
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double a[2500050];
void init()
{
double sum=0.0;
for(int i=1; i<100000001; i++)
{
sum+=1.0/i;
if(i%50==0) a[i/50]=sum; //每隔49个记录一次。
}
}
int main()
{
init();
int t,flag=1;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int f=n/50;
double ans=a[f];
for(int i=50*f+1; i<=n; i++) //很明显循环在50以内
ans+=1.0/i;
printf("Case %d: %.10lf\n",flag++,ans);
}
return 0;
}

View File

@ -0,0 +1,42 @@
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+5;
const int size=100;
double hn[N];
void gethn(){
int i,j,k;
double temp;
hn[0]=0;
temp=0;
k=1;
for(i=1;i<=N;i++){
for(j=1;j<=size;j++){
temp+=(1.0)/k;
k++;
}
hn[i]=temp;
}
}
double readhn(int x){
double ans;
int c=x%size;
ans=hn[x/size];
for(int i=x-c+1;i<=x;i++) ans+=1.0/i;
return ans;
}
int main(){
gethn();
int i,t,n;
scanf("%d",&t);
for(i=1;i<=t;i++){
scanf("%d",&n);
printf("Case %d: %.10lf\n",i,readhn(n));
}
return 0;
}

View File

@ -0,0 +1,34 @@
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define r 0.57721566490153286060651209//Å·À­³£Êý
using namespace std;
double a[10010];
int main()
{
a[1]=1.0;
for(int i=2; i<10000; i++)
a[i]=a[i-1]+1.0/i;
int t;
scanf("%d",&t);
int o=1;
while(t--)
{
int n;
double res=0.0;
scanf("%d",&n);
if(n<10000)
{
printf("Case %d: ",o++);
printf("%.10lf\n",a[n]);
}
else
{
printf("Case %d: ",o++);
double t=log(n)+r+1.0/(2*n);
printf("%.10lf\n",t);
}
}
return 0;
}

View File

@ -1,12 +1,20 @@
# 题目
* 链接
# N - Harmonic Number
* https://vjudge.net/contest/509210#problem/N
### 题意
### 做法
h(n)=1/1+1/2+……+1/n;n<=1e8
### 做法(2种)
对应两个代码
1.分层打表每50/100个记录一次查的时候再接着算
2.调和级数近似公式前1e4打表后面的调和级数近似公式因为此公式只适用于n很大的情况
### 关键词
基础数论、调和级数近似公式、分层打表、欧拉常数
### 易错点
*
* //lf->double 不是llf
* //cmath 中log就是ln
* 直接用int/long long扩大倍数打表
### 工具箱
*
* doubl&%lf https://blog.csdn.net/weixin_46585199/article/details/119044763
* 调和级数近似公式f(n)=ln(n)+r+1.0/(2*n),r是欧拉常数
//注意此公式只适用于n很大的情况。
* #define r 0.57721566490153286060651209//欧拉常数