zoukankan      html  css  js  c++  java
  • LightOJ 1234 Harmonic Number 调和级数部分和

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1234

    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足够大时它无穷大 直接公式解。

    1.虽然输出五花八门,但是不用管它,精度能保证在10 ^-8就没问题,直接用%.10lf 即可;

    2. n的范围是10^8,肯定不能正常跑,但是我们有公式,不怕,前面10000个可以正常打表,后面的我们就用公式,再说了,这个公式能成立,本来就是在n比较大的时候,公式如下:  r为常数,r=0.57721566490153286060651209(r就是欧拉常数)。

    特别注意,由于题目要求精度为10^-8,常数r也是前人推导出来的,然而也只推导了有限位数,所以正常利用这个公式,并不能达到精度要求,我们只好比较样例和我们自己输出的数据,增添一些可行的项,经尝试,在原公式的基础上,再减去一个1.0/(2*n)恰好可以满足精度,也算是投机取巧了。

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<queue>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<iostream>
     8 
     9 using namespace std;
    10 typedef long long LL;
    11 
    12 #define INF 0x3f3f3f3f
    13 #define N 12000
    14 #define mod 1000000007
    15 #define R 0.57721566490153286060651209///R就是欧拉常数
    16 
    17 double a[N];
    18 
    19 int main()
    20 {
    21     int T,k,i,x;
    22     double sum=0.0;
    23 
    24     a[1]=1;
    25     for(i=2;i<=10000;i++)
    26         a[i]=a[i-1]+1.0/i;
    27 
    28     scanf("%d", &T);
    29 
    30     k=1;
    31     while(T--)
    32     {
    33         printf("Case %d: ", k++);
    34         scanf("%d", &x);
    35         if(x<=10000)
    36             printf("%.10f
    ", a[x]);
    37         else
    38         {
    39             sum=log(x+1)+R-1.0/(2*x);
    40             printf("%.10f
    ", sum);
    41         }
    42     }
    43     return 0;
    44 }
    45 /*sum=log(n+1)+R-1.0/(2*n);*/

    有大神说:可以思维逆转,让我们用另一种思路再去看这个题目。

    如果只靠打表,而且是有技术含量的打表,也能很好的解决这个问题,既然10^8的表我们打不出来,但是200万的表我们还是能打的,这样一来,我们先平均分而且间隔着,每50个记录一个,先把分布在10^8数据中的值放在表里,真正计算时,我们便先找到距离我们的n最近的且小于n的在表中存过数据的一个数,然后再在这个数的基础上递推这往下算,这样一来,便大大降低了时间复杂度,太啰嗦了,还是看代码吧!

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<queue>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<iostream>
     8 
     9 using namespace std;
    10 typedef long long LL;
    11 
    12 #define INF 0x3f3f3f3f
    13 #define N 2100000
    14 #define MAXN 100000000
    15 #define mod 1000000007
    16 #define R 0.57721566490153286060651209///R就是欧拉常数
    17 
    18 double a[N];
    19 
    20 int main()
    21 {
    22     int T,k,i,x,c;
    23     double sum=0.0;
    24 
    25     a[0]=0;
    26     c=1;
    27     for(i=1;i<=MAXN;i++)
    28     {
    29          sum+=1.0/i;
    30          if(i%50==0)
    31             a[c++]=sum;
    32     }
    33 
    34     scanf("%d", &T);
    35 
    36     k=1;
    37     while(T--)
    38     {
    39 
    40         scanf("%d", &x);
    41 
    42         int num=x/50;
    43         double s;
    44         s=a[num];
    45         for(i=50*num+1;i<=x;i++)
    46         s+=1.0/i;
    47        printf("Case %d: %.10f
    ", k++, s);
    48     }
    49     return 0;
    50 }
    51 /*sum=log(n+1)+R-1.0/(2*n);*/
  • 相关阅读:
    C代码调用Java代码
    简易的美图秀秀利用别人的so库
    C代码输出日志
    JAVA向C传递数据
    JNI使用常见错误
    JNI的开发步骤
    NDk的目录
    交叉编译
    jquery的一点点认识
    [效率提升]工作中的那些命令行
  • 原文地址:https://www.cnblogs.com/weiyuan/p/5737273.html
Copyright © 2011-2022 走看看