题解:洛谷 P2669 金币
【题目来源】
洛谷:P2669 [NOIP 2015 普及组] 金币 - 洛谷
【题目描述】
国王将金币作为工资,发放给忠诚的骑士。第一天,骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天(第七、八、九、十天),每天收到四枚金币……;这种工资发放模式会一直这样延续下去:当连续 nn 天每天收到 nn 枚金币后,骑士会在之后的连续 \(n+1\) 天里,每天收到 \(n+1\) 枚金币。
请计算在前 \(k\) 天里,骑士一共获得了多少金币。
【输入】
一个正整数 \(k\),表示发放金币的天数。
【输出】
一个正整数,即骑士收到的金币数。
【输入样例】
6
【输出样例】
14
【核心思想】
-
问题分析:给定天数 \(k\),工资发放模式为:第1天发1枚,接下来2天每天发2枚,接下来3天每天发3枚,以此类推。求前 \(k\) 天累计获得的金币总数。这是一个双重循环模拟问题。
-
算法选择:
- 外层枚举周期:\(i\) 表示当前周期每天发放 \(i\) 枚金币,持续 \(i\) 天
- 内层枚举天数:\(j\) 从 \(1\) 到 \(i\),每天累加 \(i\) 枚金币
- 提前终止:当累计天数
day == k时立即输出结果并结束程序
-
关键步骤:
- 读入数据:
cin >> k - 初始化:
day = 0, ans = 0 - 外层循环(\(i\) 从 \(1\) 到 \(10000\)):枚举每个发放周期
- 内层循环(\(j\) 从 \(1\) 到 \(i\)):枚举周期内的每一天
ans += i:每天增加 \(i\) 枚金币day++:累计天数加1- 若
day == k:输出ans并return 0
- 内层循环(\(j\) 从 \(1\) 到 \(i\)):枚举周期内的每一天
- 输出结果:前 \(k\) 天累计金币数
- 读入数据:
-
时间/空间复杂度:
- 时间复杂度:\(O(\sqrt{k})\),因 \(1+2+\cdots+n \approx \frac{n^2}{2}\),达到 \(k\) 天需要约 \(\sqrt{2k}\) 个周期
- 空间复杂度:\(O(1)\),仅需常数个变量
-
周期模拟的核心思想:
- 嵌套周期结构:外层控制每天发放的金币数 \(i\),内层控制该金币数持续的天数 \(i\),形成"第 \(i\) 个周期持续 \(i\) 天、每天 \(i\) 枚"的模式
- 即时终止优化:无需预先计算完整周期,达到 \(k\) 天立即停止,避免多余计算
- 累加而非乘积:不直接用公式 \(i \times i\),而是逐天累加,便于在任意天终止
- 适用于周期累加、嵌套循环模拟、提前终止类入门问题
【算法标签】
入门 #数学
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int k, day, ans;
int main()
{
cin >> k; //输入k
for (int i=1; i<=10000; i++) { // 枚举“之后i天”,如“之后2天”,“之后3天”
for (int j=1; j<=i; j++) { // 枚举i天
ans += i; // 每天金币数增加i
day++; // 第day天
if (day==k) { // 如果达到第k天,输出结果,并结束程序
cout << ans << endl;
return 0;
}
}
}
return 0;
}
【运行结果】
6
14
浙公网安备 33010602011771号