题解
【入门】有趣的数字图形
1 条题解
-
0
解题思路
要输出一个 n 行 n 列的方阵,先来观察它的规律(以 n=4 为例):
1 3 8 20 3 2 5 12 8 5 3 7 20 12 7 4规律一:方阵关于主对角线对称。 比如 (1,2) 和 (2,1) 都是 3,(1,3) 和 (3,1) 都是 8。
规律二:看第一行(也是第一列)。 1, 3, 8, 20:
- 3 = 1 × 2 + 1
- 8 = 3 × 2 + 2
- 20 = 8 × 2 + 4
后一个数等于前一个数乘以 2,再依次加上 1、2、4、8……(这些数是 2 的幂)。
规律三:每条斜带里的数沿对角线方向是等差的。
- 主对角线(距离 0):1、2、3、4,每步加 1
- 紧挨着主对角线的两条带(距离 1):3、5、7,每步加 2
- 再外一圈(距离 2):8、12,每步加 4
每步加的数 = 2 的(离主对角线的距离)次方。
所以计算方法:
- 先算出第一行的所有数,存在数组 b 里
- 对每个格子 (i,j):
- 用对称性,只按 i≤j 来算
- 它离主对角线的距离 d = j-i
- 这条斜带的起点是 b[d+1]
- 从起点沿对角线再走 (i-1) 步,每步加 2 的 d 次方
- 所以值 = b[d+1] + (i-1) × 2^d
举例:n=4 时格子 (2,4):d=2,起点 b[3]=8,走 1 步加 4,得到 8+4=12,正是样例里的数。
参考代码
#include <iostream> #include <iomanip> using namespace std; int a[15][15]; // 方阵 int b[15]; // b[k]:第一行(也就是第一列)的第 k 个数 int p2[15]; // p2[k] = 2 的 k 次方 int main() { int n; cin >> n; // 先算 2 的幂:1, 2, 4, 8 ... p2[0] = 1; for (int k = 1; k <= n; k++) { p2[k] = p2[k - 1] * 2; } // 第一行的数:1, 3, 8, 20 ... // 规律:后一个数 = 前一个数 × 2,再依次加上 1, 2, 4, 8 ... b[1] = 1; for (int k = 2; k <= n; k++) { b[k] = 2 * b[k - 1] + p2[k - 2]; } // 填整个方阵 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { // 方阵关于主对角线对称,只按 i<=j 的情况算 int x = i, y = j; if (x > y) { int z = x; x = y; y = z; // 交换,保证 x<=y } int d = y - x; // 离主对角线的距离 // 起点是 b[d+1],再沿着对角线走 (x-1) 步,每步加 p2[d] a[i][j] = b[d + 1] + (x - 1) * p2[d]; } } // 输出方阵,每个数字场宽为 5 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { cout << setw(5) << a[i][j]; } cout << endl; } return 0; }复杂度分析
- 时间复杂度:O(n²),每个格子算一次
- 空间复杂度:O(n²),存整个方阵
- 1