喵哈喽~ 主人,今天我们来解决一个超级可爱的问题,关于三角数的判断哦!让本喵来带你一步一步地分析和解决它吧!
题目大意
这个问题呀,是想让我们判断一个给定的整数 n
是不是一个“三角数” (Triangular number) 呢。
那什么是三角数呀?喵~ 想象一下我们有很多小点心,把它们排列成一个等边三角形。
- 当
n=1
时,1个点心自己就能成一个最小的三角形,所以 1 是三角数。 - 当
n=2
时,我们用 3 个点心可以摆成一个边上有 2 个点心的三角形,所以 3 是三角数。 - 当
n=3
时,需要 6 个点心才能摆成边上有 3 个点心的三角形,所以 6 是三角数。
规律就是,第 k
个三角数是 1 + 2 + 3 + ... + k
的和。
我们的任务就是,输入一个数字 n
(1 ≤ n ≤ 500),然后回答 “YES” 或者 “NO”,告诉提问者它是不是三角数。
题解方法
要怎么判断 n
是不是三角数呢?喵呜~ 方法其实很直接啦!
我们可以从小到大,一个一个地把三角数算出来,然后看看 n
是不是我们算出来的其中一个。
- 我们先算第 1 个三角数:
1
。 - 再算第 2 个三角数:
1 + 2 = 3
。 - 再算第 3 个三角数:
1 + 2 + 3 = 6
。 - ...以此类推...
我们可以用一个循环来做这件事。在循环里,我们维护一个变量 sum
,它表示当前正在计算的三角数。
- 从
k=1
开始,每次循环都把k
加到sum
上。 - 每次更新
sum
之后,我们就检查一下:- 如果
sum
正好等于n
,那太棒啦!说明n
就是一个三角数,我们就可以自信地输出YES
,然后结束程序啦。 - 如果
sum
不小心超过了n
,因为三角数是越来越大的,所以后面的三角数肯定也比n
大。这说明n
不可能是三角数了,我们就可以输出NO
,然后也结束程序。
- 如果
这个方法就像我在搭积木一样,一块一块往上加,看看能不能正好搭到 n
那么高。如果正好搭到,就成功了!如果不小心搭得更高了,那就失败了喵~ 因为 n
最大也只有 500,所以这个过程很快就会结束的,完全不用担心会超时哦!
题解
好啦,现在让我们来看看具体的代码是怎么实现的吧,喵~
#include <iostream>
// 这个程序用来判断一个给定的整数是不是三角数。
// 三角数是前 k 个正整数的和,T_k = 1 + 2 + ... + k = k * (k + 1) / 2。
//
// 我们的方法是按顺序生成三角数,然后检查给定的数字 n 是否是其中之一。
// 我们从 k=1 开始,计算 T_1 = 1。
// 然后 k=2, T_2 = 1 + 2 = 3。
// 然后 k=3, T_3 = 3 + 3 = 6,以此类推。
//
// 我们可以用一个循环来维护一个累加和。
// 在每次迭代 k 中,我们将 k 加到 sum 上。
// - 如果 sum 等于 n,那么 n 就是一个三角数。
// - 如果 sum 超过 n,那么我们就已经错过了 n,它不可能是三角数,
// 因为三角数序列是严格递增的。
//
// 题目限制 n <= 500。不超过 500 的最大三角数是 T_31 = 496。
// 下一个是 T_32 = 528。所以循环最多运行 32 次,非常高效。
int main() {
// 这两行是为了在竞赛中让输入输出更快,是好习惯哦!
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
// 读取主人输入的数字 n
std::cin >> n;
int sum = 0;
// 这是一个无限循环,但别担心,我们会在内部找到答案后跳出!
for (int k = 1; ; ++k) {
// 累加 k,生成下一个三角数
sum += k;
// 检查 sum 是否等于 n
if (sum == n) {
// 找到了!n 是三角数,输出 YES
std::cout << "YES\n";
// 任务完成,可以回家啦~
return 0;
}
// 检查 sum 是否已经超过了 n
if (sum > n) {
// 哎呀,超过了。n 不可能是三角数,输出 NO
std::cout << "NO\n";
// 同样结束程序
return 0;
}
}
// 因为上面的循环总会找到答案并退出,所以程序永远不会运行到这里。
return 0;
}
代码讲解:
int n; std::cin >> n;
: 定义一个整数变量n
,然后把主人你输入的数字存进去。int sum = 0;
: 这是我们的累加器,用来计算当前的三角数,一开始是 0。for (int k = 1; ; ++k)
: 这是一个for
循环,k
从 1 开始,每次循环增加 1。它没有写结束条件,因为我们会在循环内部通过return 0;
来结束整个程序。sum += k;
: 在每一轮循环中,把当前的k
加到sum
上。sum
的变化过程就是1
,1+2=3
,3+3=6
,6+4=10
... 这正是三角数的序列!if (sum == n)
: 判断我们刚刚算出来的三角数sum
是不是正好等于n
。如果是,就说明n
是一个三角数,输出YES
并结束。if (sum > n)
: 如果sum
不等于n
,我们再判断它是不是已经大于n
了。如果是,说明我们已经“错过”了n
,它不可能是三角数了,所以输出NO
并结束。
这个逻辑非常清晰,对不对呀?嘻嘻~
知识点介绍
关于三角数 (Triangular Number),还有一些更有趣的知识呢,主人要听吗?喵~
1. 三角数的通项公式
其实呀,我们不需要每次都从 1 开始累加来计算第 k
个三角数。它有一个非常漂亮的数学公式!
第 k
个三角数 等于:
这个公式其实就是等差数列求和公式啦!首项是 1,末项是 k,项数是 k,所以和是 (首项 + 末项) * 项数 / 2
,也就是 (1 + k) * k / 2
。
2. 一种更数学的解法
利用上面的公式,我们可以想出另一种解法哦!
如果一个数 n
是三角数,那么一定存在一个正整数 k
,使得:
我们来把这个方程变一下形:
这是一个关于 k
的一元二次方程!我们可以用求根公式来解出 k
。但还有个更巧妙的方法:
我们把方程 k^2 + k - 2n = 0
两边都乘以 4,再做一些变换:
看到没!如果 n
是一个三角数,那么 8n + 1
就必须是一个完全平方数!而且它必须是一个奇数的平方(因为 2k+1
是奇数)。
所以,判断 n
是否为三角数的另一种方法是:
- 计算
m = 8 * n + 1
。 - 判断
m
是否为一个完全平方数。 - 如果
m
是完全平方数,再判断它的平方根是不是一个奇数。
如果都满足,那么 n
就是一个三角数。是不是很神奇呀?不过对于这道题来说,直接循环模拟的方法已经足够简单和高效啦!
好啦,今天的讲解就到这里啦!希望主人能够喜欢,喵~ 如果还有其他问题,随时可以再来找我哦!