数值分析PTA第一题

来源:互联网 发布:淘宝客新建推广位 编辑:程序博客网 时间:2024/05/16 16:21

请数值分析课的同学切勿直接使用代码提交,谢谢
Produce a table of the values of the series ϕ(x)=k=01k(k+x)for the
for the 3001 values of xx, xx = 0.0, 0.1, 0.2, …, 300.00. All entries of the table must have an absolute error less than 1010
​​ . This problem is based on a problem from Hamming (1962), when mainframes were very slow by today’s microcomputer standards.

void Series_Sum( double sum[] );

where double sum[]is an array of 3001 entries, each contains a value of ϕ(x) for x=0.0,0.1,0.2,…,300.00

#include <stdio.h>void Series_Sum( double sum[] );int main(){    int i;    double x, sum[3001];    Series_Sum( sum );    x = 0.0;    for (i=0; i<3001; i++)        printf("%6.2f %16.12f\n", x + (double)i * 0.10, sum[i]);    return 0;}/* Your function will be put here */

Hint:

The problem with summing the sequence in equation (1) is that too many terms may be required to complete the summation in the given time. Additionally, if enough terms were to be summed, roundoff would render any typical double precision computation useless for the desired precision.

To improve the convergence of the summation process note that

1k(k+1)=1k1k+1​​ ……(2)

which implies ϕ(1)=1.0 One can then produce a series for ϕ(x)ϕ(1) which converges faster than the original series. This series not only converges much faster, it also reduces roundoff loss.

This process of finding a faster converging series may be repeated again on the second series to produce a third sequence, which converges even more rapidly than the second.

The following equation is helpful in determining how may items are required in summing the series above.

k=n1kr<n11xrdxfor k>1 and r1……(3)
这题和ZOJ_1007题很像,只是ZOJ_1007题的取值为0-2,如果此题按照ZOJ_1007的来,先减去ϕ(1)在减去ϕ(2),会导致精度不足,因此我们可以先计算出整数时候不包0是的ϕ(n),然后计算非整数的ϕ(x),ϕ(x) 计算与之前的类似,只是减去的是与其相邻的后面两个整数,而非0与1,但是该题目要求在50ms运行,两次相减是不够的,因此我们进行三次相减,则在1000次循环中就能达到所要求的精度

/*author ZJU_Nor-His*/#include <stdio.h>void Series_Sum(double sum[]);int main(){    int i;    double x, sum[3001];    Series_Sum(sum);    x = 0.0;    for (i = 0; i<3001; i++)        printf("%6.2f %16.12f\n", x + (double)i * 0.10, sum[i]);    return 0;}void Series_Sum(double sum[]){    int i = 0;    double j = 0;    int xy;    double sum_index = 0.0;    double x = 0.0;    for (i = 1; i < 301; i++)    {        sum_index = 0.0;        for (j = 1; j <=i; j++)        {            sum_index += 1.0 / j;        }        sum[i * 10] = sum_index/i;    }    for (i = 0; i < 3001; i++)    {        sum_index = 0.0;        if (i == 0||i%10!=0)        {            if (i < 2980)            {                xy = i/10 + 1;            }            else            {                xy = i/10-1;            }            for (j = 1; j < 1500; j++)            {                sum_index += 1.0 / (j*(j + xy)*(j + xy + 1)*(j+x)*(j + xy + 2));            }            sum[i] = (xy - x)*((xy - x+ 1)*(sum_index*(xy-x+2)+(sum[xy*10]+sum[xy*10+20]-2*sum[xy*10+10])/2) + sum[xy*10] - sum[xy*10 + 10]) + sum[xy*10];        }        x += 0.1;    }    return;}
0 0