PTA | 数值分析 | 题解汇总

【6-1】Numerical Summation of a Series

求: ϕ ( x ) \phi(x) ϕ(x),其中 x x x 0.0 , 0.1 , 0.2 , . . . , 300.0 0.0, 0.1, 0.2, ..., 300.0 0.0,0.1,0.2,...,300.0
条件:
1) ϕ ( x ) = ∑ k = 1 ∞ 1 k ( k + x ) \phi(x) = \sum_{k = 1} ^ {\infty} \frac{1}{k(k + x)} ϕ(x)=k=1k(k+x)1
2)对于输出的每一项,要求绝对误差小于 1 0 − 10 10 ^ {-10} 1010
3)时限为 100 100 100 ms

分析:一种简单暴力的想法是设置一个阈值 T T T:对 k ≤ T k \le T kT,直接暴力累加;对 k > T k > T k>T,直接估计。然而,在指定的时间内,不管如何设置 T T T,精度都远远不够。

考虑对 ϕ ( x ) \phi(x) ϕ(x) 做一些转化,使得转化后的对象 μ ( x ) \mu(x) μ(x) 收敛得更快,对转化后的对象 μ ( x ) \mu(x) μ(x) 用相同的方法计算,然后再根据 ϕ ( x ) \phi(x) ϕ(x) μ ( x ) \mu(x) μ(x) 的关系,计算得到 ϕ ( x ) \phi(x) ϕ(x)

注意到
ϕ ( 1 ) = ∑ k = 1 ∞ 1 k ( k + 1 ) = 1 \phi(1) = \sum_{k = 1} ^ {\infty} \frac{1}{k(k + 1)} = 1 ϕ(1)=k=1k(k+1)1=1
ϕ ( x ) \phi(x) ϕ(x) 作转化:令 ϕ ( x ) \phi(x) ϕ(x) 减去 ϕ ( 1 ) \phi(1) ϕ(1),得
ϕ ( x ) − ϕ ( 1 ) = ( 1 − x ) ∑ k = 1 ∞ 1 k ( k + 1 ) ( k + x ) = ( 1 − x ) μ ( x ) \phi(x) - \phi(1) = (1 - x)\sum_{k = 1} ^ {\infty} \frac{1}{k(k + 1)(k + x)} = (1 - x) \mu(x) ϕ(x)ϕ(1)=(1x)k=1k(k+1)(k+x)1=(1x)μ(x)
然而这样还是过不了。

正解的做法应该是对 μ ( x ) \mu(x) μ(x) 继续进行变换,然而我又变换了三四次,依然无法满足题意要求,误差还越来越大(我猜测这是因为对转化量的的要求越来越高)。

只能去考虑对于不同的 x x x ϕ ( x ) \phi(x) ϕ(x) 之间存在什么联系。

先对 ϕ ( x ) \phi(x) ϕ(x) 进行裂项转化:
ϕ ( x ) = ∑ k = 1 ∞ 1 k ( k + x ) = 1 x ∑ k = 1 ∞ ( 1 k − 1 k + x ) \phi(x) = \sum_{k = 1} ^ {\infty} \frac{1}{k(k + x)} = \frac{1}{x} \sum_{k = 1} ^ {\infty} (\frac{1}{k} - \frac{1}{k + x}) ϕ(x)=k=1k(k+x)1=x1k=1(k1k+x1)

ϕ ( x + 1 ) = ∑ k = 1 ∞ 1 k ( k + x + 1 ) = 1 x + 1 ∑ k = 1 ∞ ( 1 k − 1 k + x + 1 ) \phi(x + 1) = \sum_{k = 1} ^ {\infty} \frac{1}{k(k + x + 1)} = \frac{1}{x + 1} \sum_{k = 1} ^ {\infty} (\frac{1}{k} - \frac{1}{k + x + 1}) ϕ(x+1)=k=1k(k+x+1)1=x+11k=1(k1k+x+11)

那么有
x ϕ ( x ) = ( x + 1 ) ϕ ( x + 1 ) − 1 1 + x x\phi(x) = (x + 1)\phi(x + 1) - \frac{1}{1 + x} xϕ(x)=(x+1)ϕ(x+1)1+x1
观察得知 ϕ \phi ϕ 越小,我们的方法计算精度越高。于是我们可以设置更大的阈值 T T T,更精确地计算 ϕ ( 0.0 , 0.1 , 0.2 , . . . , 0.9 ) \phi(0.0, 0.1, 0.2, ..., 0.9) ϕ(0.0,0.1,0.2,...,0.9),然后根据上面的等式关系,推出所有的解。


【6-2】Root of a Polynomial

求: x x x
已知:
1) n n n 次多项式 p ( x ) = c n x n + c n − 1 x n − 1 + . . . + c 1 x + c 0 p(x) = c_n x ^ n + c_{n - 1} x ^ {n - 1} + ... + c_1x + c_0 p(x)=cnxn+cn1xn1+...+c1x+c0
2) a , b a, b a,b
条件:
1) p ( x ) = 0 p(x) = 0 p(x)=0
2) a < x < b a < x < b a<x<b
2)保证 x x x 有且仅有一个解

注意事项:
1)有一个测试点在 x = b x = b x=b 处有零点,但实际答案为 ( a , b ) (a, b) (a,b) 中的另一个零点。
2)在做牛顿迭代法的时候,需要用一个更优秀的迭代公式,以及需要取多个迭代的初始值。


【6-3】There is No Free Lunch
求: c i c_i ci
已知: n ( ≤ 10000 ) n(\le 10000) n(10000), p 1 , p 2 , . . . , p n p_1, p_2, ..., p_n p1,p2,...,pn
条件:
( 2 1 2 1 2 1 2 2 1 2 1 2 2 1 2 1 2 2 1 2 ⋱ ⋱ ⋱ 1 2 2 1 2 1 2 2 1 2 1 2 1 2 2 ) ( c 1 c 2 c 3 c 4 ⋮ c n − 2 c n − 1 c n ) = ( p 1 p 2 p 3 p 4 ⋮ p n − 2 p n − 1 p n ) \begin{pmatrix} 2 & {1 \over 2} & & & & & & {1 \over 2} \\ {1 \over 2} & 2 & {1 \over 2} & & & \\ & {1 \over 2} & 2 & {1 \over 2} & \\ & & {1 \over 2} & 2 & {1 \over 2} \\ & & & \ddots & \ddots & \ddots \\ & & & & {1 \over 2} & 2 & {1 \over 2} \\ & & & & & {1 \over 2} & 2 & {1 \over 2} \\ {1 \over 2} & & & & & & {1 \over 2} & 2 \end{pmatrix} \begin{pmatrix} c_1 \\ c_2 \\ c_3 \\ c_4 \\ \vdots \\ c_{n - 2} \\ c_{n - 1} \\ c_n \end{pmatrix} = \begin{pmatrix} p_1 \\ p_2 \\ p_3 \\ p_4 \\ \vdots \\ p_{n - 2} \\ p_{n - 1} \\ p_n \end{pmatrix} 22121212212122121221212212122121212c1c2c3c4cn2cn1cn=p1p2p3p4pn2pn1pn

没有学标准做法,直接自己胡了一个线性算法过了。
用 (1, 1) 消去 (2, 1) 和 (n, 1)。
用 (2, 2) 消去 (3, 2) 和 (n, 2)。
用 (3, 3) 消去 (4, 3) 和 (n, 3)。

用 (n - 2, n - 2) 消去 (n - 1, n - 2) 和 (n - 2, n - 2)。
可以发现,我们只需要维护主对角线的元素、最后一列的元素以及该行元素线性组合得到的值,并得到如下矩阵:
( ? ? . . . ? B 1 ? ? . . . ? B 2 ? ? . . . ? B 3 ⋱ ⋱ ⋮ ⋮ ? ? ? B n − 2 ? ? B n − 1 ? ? B n ) \begin{pmatrix} ? & ? & & & ... & & ? & B_1\\ & ? & ? & & ... & & ? & B_2 \\ & & ? & ? & ... & & ? & B_3 \\ & & & \ddots & \ddots & &\vdots & \vdots \\ & & & & ? & ? & ? & B_{n - 2} \\ & & & & & ? & ? & B_{n - 1} \\ & & & & & ? & ? & B_n \end{pmatrix} ??????.........??????????B1B2B3Bn2Bn1Bn
首先,我们用行列式解出 c n − 1 , c n c_{n - 1}, c_n cn1,cn,然后可以轻松递推得到 c n − 2 , c n − 3 , . . . , c 1 c_{n - 2}, c_{n - 3}, ..., c_1 cn2,cn3,...,c1


【6-4】Compare Methods of Jacobi with Gauss-Seidel

先调整主元,然后就是模板题。

Jacobi:

for (int it = 1; it <= MAXN; it ++) {
	for (int i = 0; i < n; i ++) {
		_x[i] = b[i];
		for (int j = 0; j < n; j ++)
			if (i != j)
				_x[i] -= a[i][j] * x[j];
		_x[i] /= a[i][i];
	}
}

Gauss:

for (int it = 1; it <= MAXN; it ++) {
	for (int i = 0; i < n; i ++) {
		_x[i] = b[i];
		for (int j = 0; j < i; j ++)
			_x[i] -= a[i][j] * _x[j];
	for (int j = i + 1; j < n; j ++)
		_x[i] -= a[i][j] * x[j];
		_x[i] /= a[i][i];
}

【6-5】Approximating Eigenvalues

对于 n n n 阶矩阵 A A A,如何求 A A A 的最大特征值 λ 1 \lambda_1 λ1
直接有
λ 1 ≈ ( A k ) i , j ( A k − 1 ) i , j \lambda_1 \approx {(A ^ k)_{i, j} \over (A ^ {k - 1})_{i, j}} λ1(Ak1)i,j(Ak)i,j

对于 n n n 阶矩阵 A A A,如何求 A A A 的最小特征值 λ n \lambda_n λn
先求 A − 1 A ^ {-1} A1 的最大特征值 λ 1 ′ \lambda_1 ' λ1,则有 λ n = 1 / λ 1 ′ \lambda_n = 1 / \lambda_1' λn=1/λ1

对于 n n n 阶矩阵 A A A,给定某个近似特征值 λ 0 \lambda_0 λ0 以及近似特征向量 x 0 x_0 x0,如何更加精确地逼近?
λ − λ 0 \lambda - \lambda_0 λλ0 是矩阵 A − λ 0 I A - \lambda_0 I Aλ0I 的最小特征值。

在解最小特征值的时候,我的做法是直接将矩阵的逆 A − 1 A ^ {-1} A1 求出来,然后每次暴力乘上 A − 1 A ^ {-1} A1 算特征值,最后取反。


【6-6】Cubic Spline

直接高斯消元法暴力解方程可过。为了建立方程组的简洁,这是我定义的宏:

#define M (4 * N)
#define A(x) (4 * (x) - 3)
#define B(x) (4 * (x) - 2)
#define C(x) (4 * (x) - 1)
#define D(x) (4 * (x) - 0)
#define NEW (tot ++)
#define ADD(x, y) (eq[tot][(x)] = (y))
#define LIN(i) (x[i] - x[i - 1])
#define SQR(i) (LIN(i) * LIN(i))
#define CUB(i) (SQR(i) * LIN(i))

这样就可以把建立方程组写得很简洁:

if (Type == 1) {
		NEW, ADD(B(1), 1), ADD(M + 1, S0);
		NEW, ADD(B(N), 1), ADD(C(N), 2 * LIN(N)), ADD(D(N), 3 * SQR(N)), ADD(M + 1, SN);
	}
	else {
		NEW, ADD(C(1), 2), ADD(M + 1, S0);
		NEW, ADD(C(N), 2), ADD(D(N), 6 * LIN(N)), ADD(M + 1, SN);
	}
	for (int I = 0; I <= N; I ++) {
		if (I > 0)
			NEW, ADD(A(I), 1), ADD(B(I), LIN(I)), ADD(C(I), SQR(I)), ADD(D(I), CUB(I)), ADD(M + 1, f[I]);
		if (I < N)
			NEW, ADD(A(I + 1), 1), ADD(M + 1, f[I]);
	}
	for (int I = 1; I <= N - 1; I ++) {
		NEW, ADD(B(I), 1), ADD(C(I), 2 * LIN(I)), ADD(D(I), 3 * SQR(I)), ADD(B(I + 1), -1);
		NEW, ADD(C(I), 2), ADD(D(I), 6 * LIN(I)), ADD(C(I + 1), -2);
	}

【6-7】Orthogonal Polynomials Approximation

在实现上,我不想写类,直接用数组存储多项式。
写得有点麻烦,可以感受一下:

	int k = 1;
	while (k < MAX_n && fabs(err) >= *eps) {
		k ++;
		cpy(tmp, phi[k - 1]);
		mov(tmp);
		double bk = inner2(tmp, phi[k - 1]) / inner2(phi[k - 1], phi[k - 1]);
		double ck = inner2(tmp, phi[k - 2]) / inner2(phi[k - 2], phi[k - 2]);
		cpy(phi[k], phi[k - 1]);
		mov(phi[k]);
		cpy(tmp, phi[k - 1]);
		mul(tmp, -bk);
		add(phi[k], tmp);
		cpy(tmp, phi[k - 2]);
		mul(tmp, -ck);
		add(phi[k], tmp);
		a[k] = inner1(phi[k], f) / inner2(phi[k], phi[k]);
		cpy(tmp, phi[k]);
		mul(tmp, a[k]);
		add(c, tmp);
		err -= a[k] * inner1(phi[k], f);
	}

【6-8】Shape Roof

微元法分析:

d l = d x ∗ 1 + d y d x 2 l = ∫ a b 1 + d y d x 2 d x = ∫ a b f0 ( x ) d x dl = dx * \sqrt{1 + {dy \over dx} ^ 2} \\ l = \int_{a} ^ b \sqrt{1 + {dy \over dx} ^ 2} dx = \int_{a} ^ b \text{f0}(x) dx dl=dx1+dxdy2 l=ab1+dxdy2 dx=abf0(x)dx

然后直接模板题。
注意设 EPS 为 1e-9,比 1e-9 大则精度不够答案错误,比 1e-9 小则不能计算出来死循环。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值