题目传送门 -> https://www.luogu.com.cn/problem/P9748
大致题意
有n个苹果,每天每隔2个苹果取走一个苹果,取若干轮。
求拿完所有苹果的天数以及最后一个苹果第几天被拿走。
思路
暴力
首先想到的就是打暴力,模拟若干天,求出每个苹果在第几轮被拿走,然后输出。
(可以理解成约瑟夫问题)
这样的写法是很简单,但缺点也很明显:太暴力了,不优雅 容易超时。
实际上,正解的代码更加简单。。。
正解
先来观察:
可以将题面中“每隔2个苹果取走一个苹果”理解为将苹果分成3组,取走每组的第一个。
这样,每次取走的就是ceil(n / 3)个。因此,第一问只要暴力模拟就可以。
(ceil(x) 表示x上取整)
对于每一轮,被取走的都是当前编号 mod 3 = 1的数:
第一轮:1,4,7,10……
第二轮:1,4,7……
(原编号2,6,11……)
对于第一轮,当n % 3 == 1时最后的苹果被取走;
如果它在第一轮没有被取走,那么它一定也排在最后。
因此,每一轮都判断当前个数n % 3是否为1,然后取最小值即可。
综上,第一问可以暴力,第二问在途中进行计算。
AC代码
#include <iostream>
using namespace std;
int myceil(double x){ //向上取整
return (int)x == x ? x : x+1;
}
int n, ans1, ans2 = -1;
int main()
{
cin >> n;
for(int i = 1; ; i++){
if (n == 0) break;
//没有剩下的就跳出
if (ans2 == -1 && n % 3 == 1) ans2 = i;
//满足条件且答案没有被记录过
n -= myceil(n / 3.0); //更新n的值
ans1++;
}
cout << ans1 << ' ' << ans2 << endl;
return 0;
}
总结
今年的第一题稍微有一点点难度(至少不像去年无脑),但仍然简单,
个人觉得难度在红/橙之间,(luogu评的橙)简化的约瑟夫问题,还是很好写的。