top1编程
← 返回题目
题解

【入门】有趣的数字图形

1 条题解

  • 0
    @ 2026-7-31 20:36:38

    解题思路

    要输出一个 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 的(离主对角线的距离)次方。

    所以计算方法:

    1. 先算出第一行的所有数,存在数组 b 里
    2. 对每个格子 (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