题目链接: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);*/