愚蠢的错误的来源

本文探讨了人们在重复进行同一任务时容易犯下愚蠢错误的现象,并提出了解决方案:通过多人共同负责同一任务来降低错误发生的概率。关键在于确保每个人都能独立思考并发挥作用。
关于愚蠢的错误的来源。
人只要经常重复做一件事情,总会犯错误的,即使的最简单的事情,只是发生概率往往很小而已。
所以人常常会犯愚蠢的错误。
解决这个问题方法之一是让多个人来一起负责一件事情,因为两个人同时犯一个愚蠢错误的可能性很小。
但是使用这个方法的原则是不能让多个人变成一个头脑,就是说让每个人都确实发挥作用。
<think> 题目要求计算递归函数solve(n)的调用次数(包括首次调用),并对1000000取模。函数定义如下: ```cpp int solve(int n) { if(n==1) return 1; else if(n==2) return 2; else if(n==3) return 4; else return solve(n-1) + solve(n-2) + solve(n-3); } ``` 我们定义$f(n)$为计算`solve(n)`时,函数被调用的总次数(包括当前调用)。根据递归结构,我们可以写出$f(n)$的递推关系: - 当$n=1$时,直接返回,没有进一步的递归调用,因此$f(1)=1$。 - 当$n=2$时,同样直接返回,$f(2)=1$。 - 当$n=3$时,直接返回,$f(3)=1$。 - 当$n>3$时,为了计算`solve(n)`,我们会调用`solve(n-1)`、`solve(n-2)`和`solve(n-3)`,因此,本次调用加上这三个递归调用的总次数为: $f(n) = 1 + f(n-1) + f(n-2) + f(n-3)$。 所以,递推关系为: $$ f(n) = \begin{cases} 1 & \text{if } n = 1,2,3 \\ 1 + f(n-1) + f(n-2) + f(n-3) & \text{if } n > 3 \end{cases} $$ 现在,我们需要计算$f(n) \mod 1000000$,其中$n$最大为100,000,000。 由于$n$很大,直接递归或普通动态规划(时间复杂度$O(n)$)会导致时间或内存超出限制(因为$n$最大1e8,O(n)的时间在C++中通常可以接受,但需要大约1e8次运算,而空间需要1e8个整数,大约400MB,可能超过内存限制,且题目要求取模,所以我们需要优化)。 但是,观察递推式,它是一个线性递推,我们可以使用矩阵快速幂来加速,将时间复杂度优化到$O(\log n)$。 递推关系: $f(n) = f(n-1) + f(n-2) + f(n-3) + 1$ 注意:这个递推式不是齐次的,因为有一个常数项。我们可以通过增加一个维度来将非齐次递推关系转化为齐次线性递推。 构造状态向量: $$ \mathbf{v}_n = \begin{pmatrix} f(n) \\ f(n-1) \\ f(n-2) \\ 1 \end{pmatrix} $$ 则: $$ \mathbf{v}_{n} = \begin{pmatrix} f(n) \\ f(n-1) \\ f(n-2) \\ 1 \end{pmatrix} = \begin{pmatrix} f(n-1) + f(n-2) + f(n-3) + 1 \\ f(n-1) \\ f(n-2) \\ 1 \end{pmatrix} $$ 将$f(n-3)$用状态向量中的最后一个分量(即$f(n-2)$的前一个)表示?实际上,我们的状态向量中并没有直接包含$f(n-3)$,但我们可以用$\mathbf{v}_{n-1}$来表示$\mathbf{v}_n$: 从$\mathbf{v}_{n-1} = \begin{pmatrix} f(n-1) \\ f(n-2) \\ f(n-3) \\ 1 \end{pmatrix}$,我们想得到$\mathbf{v}_n$: $$ \mathbf{v}_n = \begin{pmatrix} f(n) \\ f(n-1) \\ f(n-2) \\ 1 \end{pmatrix} = \begin{pmatrix} 1\cdot f(n-1) + 1\cdot f(n-2) + 1\cdot f(n-3) + 1\cdot 1 \\ 1\cdot f(n-1) + 0\cdot f(n-2) + 0\cdot f(n-3) + 0\cdot 1 \\ 0\cdot f(n-1) + 1\cdot f(n-2) + 0\cdot f(n-3) + 0\cdot 1 \\ 0\cdot f(n-1) + 0\cdot f(n-2) + 0\cdot f(n-3) + 1\cdot 1 \end{pmatrix} $$ 因此,转移矩阵$A$为: $$ A = \begin{pmatrix} 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} $$ 验证: $$ A \times \mathbf{v}_{n-1} = \begin{pmatrix} 1 & 1 & 1 & 1 \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} f(n-1) \\ f(n-2) \\ f(n-3) \\ 1 \end{pmatrix} = \begin{pmatrix} f(n-1)+f(n-2)+f(n-3)+1 \\ f(n-1) \\ f(n-2) \\ 1 \end{pmatrix} = \mathbf{v}_n $$ 因此,有: $$ \mathbf{v}_n = A \times \mathbf{v}_{n-1} $$ 进而: $$ \mathbf{v}_n = A^{n-3} \times \mathbf{v}_3 $$ 其中,初始向量$\mathbf{v}_3 = \begin{pmatrix} f(3) \\ f(2) \\ f(1) \\ 1 \end{pmatrix} = \begin{pmatrix} 1 \\ 1 \\ 1 \\ 1 \end{pmatrix}$(因为$f(1)=1, f(2)=1, f(3)=1$)。 注意:我们的递推从$n=4$开始,所以当$n=3$时,我们直接使用初始向量。对于$n<3$,我们单独处理。 所以,计算步骤: 1. 如果$n \leq 3$,则$f(n)=1$,直接输出1。 2. 否则,我们需要计算$A^{n-3}$,然后乘以初始向量$\mathbf{v}_3$,得到$\mathbf{v}_n$,取第一个分量(即$f(n)$)并模1000000。 由于$n$最大为100,000,000,因此指数$n-3$最大为99999997,我们可以用矩阵快速幂在$O(\log n)$时间内计算。 矩阵快速幂: - 定义4x4矩阵的乘法(模1000000)。 - 快速幂算法:将指数分解为二进制,通过矩阵的平方和乘法来加速。 注意:因为取模1000000,所以每次矩阵乘法运算后都要对每个元素取模。 步骤: 1. 读入n。 2. 如果n<=3,输出1(因为调用次数为1)。 3. 否则,初始化转移矩阵A。 4. 计算矩阵T = A^(n-3)。 5. 用T乘以初始向量v3 = {1,1,1,1}(按列向量乘,注意顺序:结果向量的第一个元素是f(n))。 6. 输出结果向量的第一个元素模1000000。 注意:矩阵乘法的顺序,以及向量的表示。 代码实现: 首先,定义矩阵乘法(4x4)和向量与矩阵的乘法(这里向量是4维,可以视为4x1矩阵)。也可以直接定义矩阵与向量乘法。 但是,由于我们只需要乘以一个向量,所以我们可以不构造完整的矩阵乘法,而是在快速幂过程中直接使用向量与矩阵的乘法?但通常,我们使用矩阵快速幂计算出转移矩阵的幂,然后再乘以初始向量。但这样需要4x4矩阵的乘法。 另一种方法是使用快速幂的过程中,每一步都乘以向量?这样我们只需要维护一个向量,然后通过快速幂的二进制分解来更新向量。这种方法称为“快速幂应用于线性递推”,我们每一步只需要计算矩阵与向量的乘积,而不需要完整的矩阵乘法。但这里,因为我们要计算矩阵的幂,所以还是需要矩阵与矩阵的乘法(因为快速幂是矩阵的幂运算)。 因此,我们实现4x4矩阵的乘法,然后做矩阵的快速幂。 矩阵快速幂步骤: - 初始化单位矩阵作为结果矩阵。 - 将指数k = n-3 - 循环(直到k为0): - 如果k是奇数,则结果矩阵 = 结果矩阵 * 基础矩阵A(然后取模) - 基础矩阵A = A * A(然后取模) - k = k / 2 然后,用结果矩阵乘以初始向量v3(4x4矩阵乘以4x1向量)。 注意:矩阵乘法的规则:设结果矩阵为T,初始向量为v,则T*v的结果是一个向量。 具体实现: 定义矩阵类(或直接用二维数组): ```cpp struct Matrix { long long m[4][4]; Matrix() { for (int i=0; i<4; i++) for (int j=0; j<4; j++) m[i][j] = 0; } }; ``` 矩阵乘法(4x4): ```cpp Matrix multiply(Matrix a, Matrix b, long long mod) { Matrix res; for (int i=0; i<4; i++) for (int j=0; j<4; j++) for (int k=0; k<4; k++) res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % mod; return res; } ``` 矩阵快速幂(矩阵的幂): ```cpp Matrix matrix_power(Matrix base, int power, long long mod) { Matrix res; // 初始化为单位矩阵 for (int i=0; i<4; i++) res.m[i][i] = 1; while (power) { if (power & 1) res = multiply(res, base, mod); base = multiply(base, base, mod); power /= 2; } return res; } ``` 然后,我们定义初始向量v3(列向量)为: v3 = {1, 1, 1, 1} // 分别代表f(3), f(2), f(1), 1 但是注意:我们的状态向量是$\mathbf{v}_3 = [f(3), f(2), f(1), 1]^T$,而转移矩阵为A,那么$\mathbf{v}_4 = A \times \mathbf{v}_3$,$\mathbf{v}_5 = A \times \mathbf{v}_4 = A^2 \times \mathbf{v}_3$,所以对于n,我们需要计算$\mathbf{v}_n = A^{n-3} \times \mathbf{v}_3$。 因此,我们计算矩阵T = A^(n-3),然后计算T * v3(注意:矩阵乘以向量,结果向量为T的第一列乘以v3[0] + T的第二列乘以v3[1] + ...,但通常我们按行乘列,所以结果向量的第i个分量为:T的第i行与v3的点积)。 具体计算: 设向量v = {v3[0], v3[1], v3[2], v3[3]} = {1,1,1,1},然后我们计算T * v: 结果向量res_vector的每个分量i: res_vector[i] = T.m[i][0]*v[0] + T.m[i][1]*v[1] + T.m[i][2]*v[2] + T.m[i][3]*v[3] 而我们只需要第一个分量(即i=0),因为状态向量$\mathbf{v}_n$的第一个分量就是$f(n)$。 所以,f(n) = (T.m[0][0]*1 + T.m[0][1]*1 + T.m[0][2]*1 + T.m[0][3]*1) % mod 但是,我们也可以直接计算这个表达式,而不需要计算整个向量。 因此,步骤: 1. 如果n<=3,直接输出1。 2. 否则,构造转移矩阵A: A = { {1,1,1,1}, {1,0,0,0}, {0,1,0,0}, {0,0,0,1} } 3. 计算T = A^(n-3) 4. 计算f(n) = (T.m[0][0] + T.m[0][1] + T.m[0][2] + T.m[0][3]) % mod 为什么?因为初始向量v3 = [1,1,1,1]^T,所以结果向量的第一个分量就是T的第一行与v3的点积。 注意:模数为1000000。 但是,当n很大时,矩阵快速幂的指数n-3可能很大(最大99999997),但快速幂的迭代次数为O(log(n)),大约27次左右(因为2^27>1e8),所以很快。 代码实现: 注意:矩阵元素用long long,因为乘法过程可能溢出int(模1000000,两个数相乘最大为1e12,long long可以容纳)。 完整代码: ```cpp #include <iostream> #include <vector> using namespace std; const long long MOD = 1000000; struct Matrix { long long m[4][4]; Matrix() { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) m[i][j] = 0; } }; Matrix multiply(Matrix a, Matrix b) { Matrix res; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD; } } } return res; } Matrix matrix_power(Matrix base, int power) { Matrix res; // 单位矩阵 for (int i = 0; i < 4; i++) res.m[i][i] = 1; while (power) { if (power & 1) res = multiply(res, base); base = multiply(base, base); power = power / 2; } return res; } int main() { int n; cin >> n; if (n <= 3) { cout << 1 << endl; // 因为调用次数为1 return 0; } // 构造转移矩阵A Matrix A; A.m[0][0] = 1; A.m[0][1] = 1; A.m[0][2] = 1; A.m[0][3] = 1; A.m[1][0] = 1; A.m[1][1] = 0; A.m[1][2] = 0; A.m[1][3] = 0; A.m[2][0] = 0; A.m[2][1] = 1; A.m[2][2] = 0; A.m[2][3] = 0; A.m[3][0] = 0; A.m[3][1] = 0; A.m[3][2] = 0; A.m[3][3] = 1; // 计算矩阵T = A^(n-3) Matrix T = matrix_power(A, n - 3); // 计算f(n) = T的第一行与向量[1,1,1,1]的点积 long long fn = 0; for (int j = 0; j < 4; j++) { fn = (fn + T.m[0][j]) % MOD; } cout << fn << endl; return 0; } ``` 注意:矩阵快速幂的指数为n-3,当n=4时,指数为1,正确。 测试: - n=1,2,3: 输出1。 - n=4: 计算f(4)=1+f(3)+f(2)+f(1)=1+1+1+1=4,所以f(4)=4?但是注意,函数调用过程:首先调用solve(4),然后它会调用solve(3)、solve(2)、solve(1)。所以调用次数为1(自己)+ f(3)+f(2)+f(1)=1+1+1+1=4。所以n=4时输出4。 用上面的代码计算n=4: 转移矩阵A的1次幂就是A本身。 T = A,所以第一行是[1,1,1,1],那么点积=1+1+1+1=4,正确。 n=5:f(5)=1+f(4)+f(3)+f(2)=1+4+1+1=7。 用矩阵:T = A^(2) = A*A 计算A*A: 第一行:A的第一行乘以A的每一列: 第一列:1*1+1*1+1*0+1*0 = 2 第二列:1*1+1*0+1*0+1*0 = 1 第三列:1*1+1*0+1*0+1*0 = 1 第四列:1*1+1*0+1*0+1*1 = 2 所以第一行:[2,1,1,2] 点积=2+1+1+2=6?但是应该是7。 错误:矩阵乘法的规则?我们定义的矩阵乘法是正常的矩阵乘法。重新计算A*A: A = [ [1,1,1,1], [1,0,0,0], [0,1,0,0], [0,0,0,1] ] A*A = 第一行:A[0]乘以A的每一列 第一列:1*1 + 1*1 + 1*0 + 1*0 = 1+1=2 第二列:1*0 + 1*0 + 1*1 + 1*0? 不对,应该是: 矩阵乘法:A[i][k] * A[k][j] 所以A的第一行乘以A的第一列:1*1 + 1*1 + 1*0 + 1*0 = 1+1=2 乘以第二列:1*1 + 1*0 + 1*0 + 1*0 = 1 乘以第三列:1*1 + 1*0 + 1*0 + 1*0 = 1 乘以第四列:1*1 + 1*0 + 1*0 + 1*1 = 1+1=2 所以第一行:[2,1,1,2] 然后乘以初始向量v3=[1,1,1,1]^T:结果向量的第一个分量=2*1+1*1+1*1+2*1=6,但实际f(5)=1+f(4)+f(3)+f(2)=1+4+1+1=7,不一致。 问题出在哪里? 重新推导递推关系: f(4)=1+f(3)+f(2)+f(1)=1+1+1+1=4 f(5)=1+f(4)+f(3)+f(2)=1+4+1+1=7 而状态向量: v4 = [f(4), f(3), f(2), 1]^T = [4,1,1,1]^T 那么v5 = A * v4 = 第一行:1*4 + 1*1 + 1*1 + 1*1 = 4+1+1+1=7 第二行:1*4 +0+0+0=4 第三行:0+1*1+0+0=1 第四行:0+0+0+1*1=1 所以v5=[7,4,1,1]^T,正确。 那为什么用A^2乘以v3不对?因为: v4 = A * v3 v5 = A * v4 = A * (A * v3) = A^2 * v3 所以v5应该是A^2乘以v3。而我们计算A^2是: A^2 = [ [2,1,1,2], [1,1,1,1], [1,0,0,0], [0,0,0,1] ] 然后乘以v3=[1,1,1,1]^T: 第一分量:2*1+1*1+1*1+2*1=2+1+1+2=6,不等于7。 错误原因:我们定义的初始向量v3=[f(3),f(2),f(1),1]^T=[1,1,1,1]^T,但根据递推,v4=A*v3,而v5=A*v4=A^2*v3。但实际计算v5时,我们期望得到7,但A^2*v3得到6。 检查转移矩阵A: v4 = A * v3 = 第一行:1*f3 +1*f2 +1*f1 +1*1 = 1+1+1+1=4 -> 正确 第二行:1*f3 +0+0+0=1 -> 正确(等于f3) 第三行:0+1*f2+0+0=1 -> 正确(等于f2) 第四行:0+0+0+1*1=1 -> 正确 所以v4=[4,1,1,1]^T v5 = A * v4 = 第一行:1*4 +1*1 +1*1 +1*1=4+1+1+1=7 ->正确 第二行:1*4+0+0+0=4 第三行:0+1*1+0+0=1 第四行:0+0+0+1*1=1 所以v5=[7,4,1,1]^T 那么,用A^2乘以v3应该得到同样的结果。但是,我们手算A^2: A = row0: [1,1,1,1] row1: [1,0,0,0] row2: [0,1,0,0] row3: [0,0,0,1] A^2 = A * A 计算每个元素: (0,0): 1*1+1*1+1*0+1*0 = 2 (0,1): 1*1+1*0+1*1+1*0 = 1+1=2? 不对,按照矩阵乘法规则: A^2的(0,0) = 第0行乘第0列 = 1*1 + 1*1 + 1*0 + 1*0 = 2 (0,1) = 第0行乘第1列 = 1*1 + 1*0 + 1*0 + 1*0 = 1 (0,2) = 第0行乘第2列 = 1*1 + 1*0 + 1*0 + 1*0 = 1 (0,3) = 第0行乘第3列 = 1*1 + 1*0 + 1*0 + 1*1 = 1+1=2 (1,0) = 第1行乘第0列 = 1*1 + 0*1 + 0*0 + 0*0 = 1 (1,1) = 1*1+0*0+0*0+0*0=1 (1,2)=1*1+0*0+0*0+0*0=1 (1,3)=1*1+0*0+0*0+0*1=1 (2,0)=0*1+1*1+0*0+0*0=1 (2,1)=0*1+1*0+0*0+0*0=0 (2,2)=0*1+1*0+0*0+0*0=0 (2,3)=0*1+1*0+0*0+0*1=0 (3,0)=0*1+0*1+0*0+1*0=0 (3,1)=0 (3,2)=0 (3,3)=1 所以A^2实际是: [ [2,1,1,2], [1,1,1,1], [1,0,0,0], [0,0,0,1] ] 然后,A^2 * v3 = 第一行:2*1 + 1*1 + 1*1 + 2*1 = 2+1+1+2=6 第二行:1*1+1*1+1*1+1*1=4 第三行:1*1+0+0+0=1 第四行:0+0+0+1*1=1 所以得到向量[6,4,1,1]^T,但是正确的v5应该是[7,4,1,1]^T。 为什么?因为我们的状态向量是[f(n), f(n-1), f(n-2), 1]^T,而v3=[f(3),f(2),f(1),1]^T,经过一次乘A得到v4,再乘一次A得到v5。但是,A^2乘以v3得到的是v5,而我们手算的v5是[7,4,1,1]^T,但这里得到6。 矛盾出现。重新检查递推关系: f(5)=1+f(4)+f(3)+f(2)=1+4+1+1=7 但是,我们的转移矩阵A在乘以v4时得到7,而A^2乘以v3得到6,说明转移矩阵没有错,而是A^2计算错了? 重新计算A^2的(0,0)位置:应该是A的第0行乘以A的第0列: A的第0行:[1,1,1,1] A的第0列:[1,1,0,0]^T -> 1*1+1*1+1*0+1*0=2,正确。 (0,1): A第0行乘以A的第1列:[1,0,0,0]^T ->1*1+1*0+1*0+1*0=1 (0,2): A第0行乘以A的第2列:[1,0,0,0]^T? 不对,A的第2列是第三个列向量,应该是[1,0,0,0]^T? 实际上,矩阵A的列: 第0列: [1,1,0,0]^T 第1列: [1,0,1,0]^T -> 不对,矩阵A我们写的是: A = [ [1,1,1,1], [1,0,0,0], [0,1,0,0], [0,0,0,1] ] 所以,第0列:1,1,0,0 第1列:1,0,1,0? 不对,第二行第一列是1?不对,矩阵A的表示: 实际上,矩阵A在内存中,我们按行存储: A.m[0][0]=1, A.m[0][1]=1, A.m[0][2]=1, A.m[0][3]=1 A.m[1][0]=1, A.m[1][1]=0, A.m[1][2]=0, A.m[1][3]=0 A.m[2][0]=0, A.m[2][1]=1, A.m[2][2]=0, A.m[2][3]=0 A.m[3][0]=0, A.m[3][1]=0, A.m[3][2]=0, A.m[3][3]=1 因此,列向量: 第0列:A.m[0][0], A.m[1][0], A.m[2][0], A.m[3][0] = [1,1,0,0]^T 第1列:A.m[0][1], A.m[1][1], A.m[2][1], A.m[3][1] = [1,0,1,0]^T -> 这里注意,A.m[1][1]是0,A.m[2][1]是1?不对,我们写的是A.m[2][1]为1?实际上,第二行第一列是1?不对,矩阵第二行是[1,0,0,0],所以第二行第一列是1,第二行第二列是0。第三行是[0,1,0,0],所以第三行第一列是0,第三行第二列是1。 所以,第1列:由所有行的第1列组成:第0行第1列=1,第1行第1列=0,第2行第1列=1(因为第三行对应索引2),第3行第1列=0。所以第1列=[1,0,1,0]^T。 那么,A^2的(0,1)位置 = 第0行([1,1,1,1])乘以第1列([1,0,1,0]^T): 1*1 + 1*0 + 1*1 + 1*0 = 1+0+1+0=2 而我们之前计算成1了!错误在这里。 所以,重新计算A^2: (0,0): [1,1,1,1] * [1,1,0,0]^T = 1*1 + 1*1 + 1*0 + 1*0 = 2 (0,1): [1,1,1,1] * [1,0,1,0]^T = 1*1 + 1*0 + 1*1 + 1*0 = 2 (0,2): [1,1,1,1] * [1,0,0,0]^T = 1*1 + 1*0 + 1*0 + 1*0 = 1 (0,3): [1,1,1,1] * [1,0,0,1]^T = 1*1 + 1*0 + 1*0 + 1*1 = 2 (1,0): [1,0,0,0] * [1,1,0,0]^T = 1*1 + 0*1 + 0*0 + 0*0 = 1 (1,1): [1,0,0,0] * [1,0,1,0]^T = 1*1 + 0*0 + 0*1 + 0*0 = 1 (1,2): [1,0,0,0] * [1,0,0,0]^T = 1 (1,3): [1,0,0,0] * [1,0,0,1]^T = 1 (2,0): [0,1,0,0] * [1,1,0,0]^T = 0*1+1*1+0*0+0*0=1 (2,1): [0,1,0,0] * [1,0,1,0]^T = 0*1+1*0+0*1+0*0=0 (2,2): [0,1,0,0] * [1,0,0,0]^T = 0 (2,3): [0,1,0,0] * [1,0,0,1]^T = 0 (3,0): [0,0,0,1] * [1,1,0,0]^T = 0 (3,1): [0,0,0,1] * [1,0,1,0]^T = 0 (3,2): [0,0,0,1] * [1,0,0,0]^T = 0 (3,3): [0,0,0,1] * [1,0,0,1]^T = 1 所以A^2 = [ [2,2,1,2], [1,1,1,1], [1,0,0,0], [0,0,0,1] ] 然后,A^2 * v3 = [2,2,1,2] * [1,1,1,1]^T = 2*1+2*1+1*1+2*1=2+2+1+2=7 -> 正确。 所以,之前是计算矩阵乘法时对列的理解错误。在代码中,我们写的是正确的矩阵乘法(三层循环),所以代码会自动处理。 因此,我们使用上面写好的代码即可。 修正后,测试n=5,输出7,正确。 再测试n=6: f(6)=1+f(5)+f(4)+f(3)=1+7+4+1=13 用矩阵:T = A^(3) = A^2 * A A^2已经得到,然后乘以A: 计算A^3 = A^2 * A 但我们不需要手算,代码会计算。我们相信代码。 注意:n很大时,快速幂的指数n-3可能达到100000000-3,但log2(100000000)≈27,所以循环27次。 最后,对1000000取模。 代码已经包含取模,所以直接运行即可。 但是,注意n最大为100000000,而矩阵快速幂中,指数为n-3,当n=100000000时,指数为99999997,在整数范围内。 运行代码,测试小数据: n=1 ->1 n=2 ->1 n=3 ->1 n=4 ->4 n=5 ->7 n=6 ->13 然后,可以测试n=7:f(7)=1+f(6)+f(5)+f(4)=1+13+7+4=25,运行代码应该输出25。 修改代码,输出n=7的结果:用矩阵A^(4)再乘以v3,即A^4等于?我们不用手算,运行代码即可。 所以,我们使用上述代码,并确保矩阵乘法正确。 提交代码时,注意输入n的范围,以及使用long long以防中间结果溢出int。 但是,在矩阵乘法中,每个元素最大可能是4 * (1000000-1) * (1000000-1) ≈ 4e12,而long long最大约9e18,所以不会溢出。 因此,最终代码如上。 注意:如果n很大,递归深度很浅(快速幂的循环次数少),所以效率很高。 我们输出调用次数,即f(n) mod 1000000。 §§相关问题§§ 1. 如果递归函数的形式发生变化(例如递推式不同),如何调整转移矩阵? 2. 对于更复杂的递归函数(包含多个递归调用和条件分支),如何计算调用次数? 3. 矩阵快速幂的时间复杂度如何分析? </think> 要计算递归函数 `solve(n)` 在输入 `n` 时的调用次数(包括首次调用),并对结果取模 1,000,000,可以使用矩阵快速幂优化递推关系。以下是完整的 C++ 实现: ```cpp #include <iostream> using namespace std; const long long MOD = 1000000; // 定义 4x4 矩阵结构 struct Matrix { long long m[4][4]; Matrix() { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) m[i][j] = 0; } }; // 矩阵乘法 (4x4) Matrix multiply(Matrix a, Matrix b) { Matrix res; for (int i = 0; i < 4
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值