☰
洛谷 P9748 [CSP-J 2023] 小苹果 c++语言
2026/10/7 15:21:54 网站建设 项目流程

老规矩 题目奉上

这次的题目有些长 不过无伤大雅

题目大意

桌子上有 n 个苹果,编号 \(1\sim n\),排成一列。 每一天操作规则:

  1. 从最左边第 1 个苹果开始,每隔 2 个拿走 1 个苹果。也就是取第 1、4、7…… 位置上的苹果(位置从 1 开始数,每 3 个里拿第 1 个)。
  2. 拿完之后,剩下苹果保持原有顺序,重新排成一列,进入下一天。

求两个答案:

  1. 拿完全部苹果一共需要多少天;
  2. 原始编号为 n 的苹果,会在第几天被拿走。

样例:输入 8,输出5 5。 意思:一共要 5 天拿完,8 号苹果在第 5 天被拿走。

拿苹果规则拆解

每隔 2 个拿 1 个: 位置序列:1,2,3,4,5,6,7,8 第一天拿位置1,4,7,剩下2,3,5,6,8,这就是新一轮的序列。

每天拿走的数量计算公式

在代码里等价于take=(n+2)/3(整数除法实现向上取整) 剩余苹果数量:n = n - take

思路分析

  1. 总天数计算循环模拟每一天:每天算出当天拿走多少苹果,更新剩余苹果数量,天数 + 1,直到苹果数量为 0,days就是总天数。
  2. 编号 n 的苹果在哪一天被拿走我们关心原始最末尾的苹果,它什么时候会被选中。 观察规律:在一轮序列中,如果当前序列长度模 3 等于 1,本轮第一个位置就是会被拿走的位置。而原始 n 号苹果,只有当它处于当前序列的第 1 位时,才会被拿走。

注意边界:n = 1,第一天就拿走,答案1 1。

C++ 完整代码

#include<bits/stdc++.h> using namespace std; typedef long long LL; int main() { LL n, days = 0, nday = 0, take = 0; cin >> n; if (n == 1) { cout << 1 << ' ' << 1 << endl; } bool falg = false; while (n > 0) { days++; if (!falg && n % 3 == 1) { nday = days; falg = true; } take = (n + (3 - 1)) / 3; n = n - take; } cout << days << ' ' << nday << endl; return 0; }

小结

这道题核心两点:

  1. 用数学式子(n+2)/3快速求每天拿走苹果的数量,不用数组模拟每一个苹果,效率很高。
  2. 找到末尾苹果被取走的条件:当当前序列长度模 3 等于 1,就是目标苹果被拿走的那一天。

拓展思考:如果直接开数组保存苹果编号模拟,n 大的时候会超时,这种数学推导的方法更适合大数据。

世间万象 纸上一隅 愿这些文字能带给你片刻启发 山高水远 我们后会有期

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询