CSP-J 2023 复赛第1题:小苹果

【题目来源】
https://www.luogu.com.cn/problem/P9748
https://www.acwing.com/problem/content/5310/

【题目描述】
小 Y 的桌子上放着 n 个苹果从左到右排成一列,编号为从 1 到 n。
小苞是小 Y 的好朋友,每天她都会从中拿走
一些苹果。
每天在拿的时候,小苞都是从左侧第 1 个苹果开始、每隔 2 个苹果拿走 1 个苹果。
随后小苞会将剩下的苹果按原先的顺序重新排成一列。
小苞想知道,多少天能拿完所有的苹果,而编号为 n 的苹果是在第几天被拿走的?

【输入格式】
输入的第一行包含一个正整数 n,表示苹果的总数。

【输出格式】
输出一行包含两个正整数,两个整数之间由一个空格隔开,分别表示小苞拿走所有苹果所需的天数以及拿走编号为 n 的苹果是在第几天。

【数据范围】
对于所有测试数据有:1≤n≤10^9。

测试点n≤特殊性质
1∼210
3∼510^3
6∼710^6
8∼910^6
1010^9

特殊性质:小苞第一天就取走编号为 n 的苹果。

【输入样例】
8

【输出样例】
5 5

【样例解释】
小苞的桌上一共放了 8 个苹果。
小苞第一天拿走了编号为 1、4、7 的苹果。
小苞第二天拿走了编号为 2、6 的苹果。
小苞第三天拿走了编号为 3 的苹果。
小苞第四天拿走了编号为 5 的苹果。
小苞第五天拿走了编号为 8 的苹果。

【算法分析】
● 由于数据规模为 10^9,所以一个一个枚举拿走的苹果必然会超时。不过可考虑一天一天枚举拿走的苹果。
● 可推算出每天拿走的苹果数为 ceil(1.0*n/3),即每天拿走
(n+2)/3 个苹果,拿完后剩余 n-ceil(1.0*n/3) 个苹果。如果 n%3==1,那么第 n 个苹果此轮会被拿走。其中,ceil() 为 C++ 中的向上取整函数。而 floor() 为 C++ 中的向下取整函数。

【算法代码一】

注意本代码中的 ceil(1.0*n/3),切记不要写成 ceil(n/3),否则将无法得出正确的向上取整值。因为,在 C++ 代码中,若 n 为整数,则 n/3 省略小数部分,自动截断为一个整数值。

#include <bits/stdc++.h>
using namespace std;
 
int days,cnt;
int main() {
    int n;
    cin>>n;
    while(n) {
        days++;
        if(cnt==0 && n%3==1) cnt=days;
        n-=ceil(1.0*n/3); //n-=(n+2)/3;
    }
    cout<<days<<" "<<cnt;
    
    return 0;
}
 
 
/*
in:8
out:5 5
*/


【算法代码二】

#include <bits/stdc++.h>
using namespace std;

int days,cnt;
int main() {
    int n;
    cin>>n;
    while(n) {
        days++;
        if(cnt==0 && n%3==1) cnt=days;
        n-=(n+2)/3;
    }
    cout<<days<<" "<<cnt;
    
    return 0;
}


/*
in:8
out:5 5
*/




【参考文献】
https://www.acwing.com/solution/content/220247/
https://blog.youkuaiyun.com/m0_59925573/article/details/136106743
https://mp.weixin.qq.com/s/zckJsihxsDT2JNBFK1ipxA






 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值