1 条题解

  • 0
    @ 2026-6-19 10:30:45

    📝 题目大意

    给定一个整数 NN0N210 \le N \le 21),按字典序从小到大输出所有满足 x+y+zNx + y + z \le N 的非负整数三元组 (x,y,z)(x, y, z)

    💡 解题思路

    1. 题目分析NN 最大仅为 2121,即使三重循环枚举所有可能的 (x,y,z)(x, y, z),最坏情况下也只需枚举 O(N3)104O(N^3) \approx 10^4 种情况,完全在时限内。因此直接暴力枚举即可。

    2. 算法推导

      • 最外层循环枚举 xx(代码中为 i),范围 0N0 \sim N
      • 第二层循环枚举 yy(代码中为 j),范围 0Nx0 \sim N - x(即 i + j <= n),因为 x+yx + y 已经不能超过 NN
      • 第三层循环枚举 zz(代码中为 k),范围 0Nxy0 \sim N - x - y(即 i + j + k <= n)。
      • 三层循环的嵌套顺序天然保证了字典序:先固定 xx 更小的,再固定 yy 更小的,最后 zz 从小到大,完全符合字典序的定义。
    3. 边界与细节

      • N=0N = 0 时,只输出 0 0 0
      • 注意第二层和第三层循环的终止条件用的是 i + j <= ni + j + k <= n,而不是 j <= nk <= n,这样可以提前剪枝,避免枚举无效的三元组。
      • 输出时每行三个整数用空格分隔,末尾换行。

    ⏱️ 复杂度分析

    • 时间复杂度O(N3)O(N^3)。合法三元组共有 CN+33=(N+3)(N+2)(N+1)6C_{N+3}^{3} = \frac{(N+3)(N+2)(N+1)}{6} 个,当 N=21N=21 时约为 20242024 个,远小于 213=926121^3 = 9261
    • 空间复杂度O(1)O(1),仅使用了常数个变量。

    💻 标准代码 (C++)

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
    	int n; scanf("%d", &n);
    	// 最外层枚举 x,天然保证字典序:x 小的先输出
    	for(int i = 0; i <= n; i++)
    	{
    		// 第二层枚举 y,满足 x + y <= n(剪枝)
    		for(int j = 0; i + j <= n; j++)
    		{
    			// 第三层枚举 z,满足 x + y + z <= n
    			for(int k = 0; i + j + k <= n; k++)
    			{
    				// 三个数三层循环,直接判断合法并输出
    				printf("%d %d %d\n", i, j, k);
    			}
    		}
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    768
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者