题目分析与关键要求

题目描述

输入正整数n(1 ≤ n ≤ 13),输出一个直角边长度为n的数字直角三角形,满足以下要求:

  1. 所有数字由递增的两位数组成(包含前导0)
  2. 直角位于左上角(第一行元素最多)
  3. 每条直角边的长度均为n

输入输出样例

输入:5 输出

0102030405
06070809
101112
1314
15

解题思路与算法设计

关键需求分解

  1. 数字序列:连续的两位数,从01开始递增
  2. 行结构:第一行n个元素,每行递减1个
  3. 格式要求:统一为两位数,不足补前导0

算法流程图

C++代码解析与优化

基础实现代码

#include <iostream>
#include <cstdio> // 使用printf进行格式化输出
using namespace std;

int main() {
    int n;
    cin >> n;        // 输入三角形的直角边长
    int a = 1;       // 初始化起始数字为1
    
    for (int i = n; i >= 1; i--) {      // 外层循环控制行数
        for (int j = i; j >= 1; j--) {  // 内层循环控制当前行元素数量
            printf("%02d", a++);        // 输出两位数并自增变量
        }
        cout << endl;                  // 每行结束换行
    }
    
    return 0;
}

核心知识点详解

1. 循环嵌套结构
for (int i = n; i >= 1; i--) {      // i从n递减到1
    for (int j = i; j >= 1; j--) {  // j从当前i递减到1
        // 元素输出代码
    }
    // 换行代码
}
  • 外层循环:控制总的行数(n行)
  • 内层循环:控制每行元素数量(第1行n个,第n行1个)
  • 递减设计:使内层循环次数逐行递减
2. 格式化输出
printf("%02d", a++);
  • %02d:格式化输出整数
    • 0:宽度不足时用0填充
    • 2:输出总宽度为2位
    • d:输出十进制整数
  • a++:先输出当前值,再自增
3. 数字序列生成技巧
  • a从1开始,每次输出后自增
  • 自动处理数字递增逻辑
  • 不需要单独计算每个位置的值

代码优化方案

1. 减少变量数量
int main() {
    int n, a = 1;
    cin >> n;
    
    while (n) {
        int cnt = n--;
        while (cnt--) 
            printf("%02d", a++);
        cout << endl;
    }
    
    return 0;
}
2. 使用C++流格式化
#include <iostream>
#include <iomanip> // 控制输出格式
using namespace std;

int main() {
    int n, a = 1;
    cin >> n;
    
    for (int row = n; row >= 1; row--) {
        for (int col = 0; col < row; col++) {
            cout << setfill('0') << setw(2) << a++;
        }
        cout << endl;
    }
    
    return 0;
}
  • setfill('0'):设置填充字符为'0'
  • setw(2):设置输出宽度为2位
3. 预分配数字数组方案
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 计算总数字个数:三角形数公式
    int total = n*(n+1)/2;
    vector<int> numbers(total);
    
    // 初始化数字序列
    for (int i = 0; i < total; i++) {
        numbers[i] = i+1;
    }
    
    // 分层输出
    int start = 0;
    for (int row = n; row >= 1; row--) {
        for (int i = 0; i < row; i++) {
            cout << setfill('0') << setw(2) << numbers[start+i];
        }
        start += row;
        cout << endl;
    }
    
    return 0;
}

关键编程技巧详解

1. 循环控制优化

循环方向选择
// 递减方式(推荐)
for (int i = n; i > 0; i--) {
    for (int j = i; j > 0; j--) {
        // 输出元素
    }
}

// 递增方式
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n - i; j++) {
        // 输出元素
    }
}

推荐递减方式原因

  1. 不需要计算偏移量
  2. 更直观的反应行元素数量
  3. 减少变量计算次数

2. 数字格式化详解

不同格式化方法比较
方法 代码实现 优点 缺点
printf printf("%02d", num) 简洁高效 需要C标准库
流操作符 cout << setfill('0') << setw(2) << num C++标准 冗长
条件语句 if(num<10) cout<<"0"; cout<<num; 直观 代码重复
格式化应用场景
// 简单数字输出
printf("%02d", num);

// 复杂格式化(如包含字符)
printf("%02d-%c", id, 'A'+type);

// 对齐表格输出
printf("%-6s|%02d", name, id);

3. 边界条件处理

输入验证
cin >> n;

// 验证输入范围
if (n < 1 || n > 13) {
    cerr << "输入超出范围:1 <= n <= 13" << endl;
    return 1;
}
输出验证
// 预期最大值计算
int max_num = n*(n+1)/2;
if (max_num <= 99) {
    // 确保两位数足够
} else {
    // 处理三位数(超出题目范围)
}

题目变式与扩展

变式1:右下角直角三角形

#include <iostream>
#include <cstdio>
using namespace std;

int main() {
    int n, a = 1;
    cin >> n;
    
    for (int i = 1; i <= n; i++) {
        // 打印前方空格
        for (int sp = n - i; sp > 0; sp--) {
            cout << "  "; // 两位数宽的空格
        }
        
        // 打印数字
        for (int j = 0; j < i; j++) {
            printf("%02d", a++);
        }
        
        cout << endl;
    }
    
    return 0;
}

输出n=5的结果

        01
      0203
    040506
  07080910
1112131415

变式2:字母直角三角

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    char ch = 'A';
    cin >> n;
    
    for (int i = n; i > 0; i--) {
        for (int j = i; j > 0; j--) {
            cout << ch++ << " "; // 字母递增
        }
        cout << endl;
    }
    
    return 0;
}

输出n=5的结果

A B C D E
F G H I 
J K L 
M N 
O

变式3:斐波那契三角

#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<int> fib = {1, 1}; // 斐波那契序列
    
    // 生成足够的斐波那契数
    for (int i = 2; i < n*(n+1)/2; i++) {
        fib.push_back(fib[i-1] + fib[i-2]);
    }
    
    int index = 0;
    
    for (int row = n; row > 0; row--) {
        for (int col = 0; col < row; col++) {
            cout << setw(4) << fib[index++];
        }
        cout << endl;
    }
    
    return 0;
}

竞赛技巧与常见错误

1. 格式化输出常见错误

// 错误示范1:忘记设置填充字符
printf("%2d", num); // 不足时用空格填充

// 错误示范2:流操作顺序错误
cout << setw(2) << setfill('0') << num; // 应先设置fill

// 解决方案:
cout << setfill('0') << setw(2) << num;

2. 循环边界陷阱

// 错误示范:数组下标越界
int numbers[n]; // n不是编译期常量

// 正确做法:
int *numbers = new int[n];
// 或使用vector
vector<int> nums(n);

3. 整数溢出风险

// 当n=13时,最大数字为13*14/2=91
// 但n>13时,例如n=20,最大数字为210(三位数)
// 需添加检测
if (a > 99) {
    printf("%3d", a); // 改为三位显示
}

典型题目推荐

题目 平台 核心知识点
数字金字塔 洛谷P1030 循环输出/格式化
字母直角三角 CodeForces #118A 字符处理
螺旋矩阵 LeetCode #54 二维数组处理
斐波那契三角 HDU #1207 数学序列
数字直角三角形 CSP-J模拟题 综合应用

"循环与格式化输出是CSP-J/S竞赛的基础功,掌握不同输出格式的区别,能大幅提升解题效率。"                                                                                                 —— NOI金牌选手经验谈

总结与学习建议

核心知识点清单

  1. 循环结构:嵌套循环的设计与优化
  2. 格式化输出
    • printf格式字符串(%02d)
    • 流操作符(setw,setfill)
  3. 二维形状生成:理解坐标系与元素定位
  4. 边界处理:输入验证与溢出检测

训练建议

  1. 基础练习:实现不同方向(上/下/左/右)的直角三角形
  2. 进阶练习:生成数字金字塔、字母矩阵等复杂图形
  3. 挑战练习:尝试动态分配空间处理更大n值
  4. 在线提交:在洛谷、Codeforces等平台搜索相关题目

更多推荐