[CSP-J 2023] 小苹果 题解

推荐测评/题面端:

解法: 

题目中说,隔 2 个苹果拿一个苹果,意味着从左侧开始在每 3 个苹果中拿出第一个苹果。

再来看看数据范围:n \le 10^9,而我们知道,两个答案都不会大于 n,这样用不上 long long 类型,用 int 就够了。

50分做法:

全模拟,我们不妨用vector来存储信息。

代码十分好懂,要说的写在注释里了。

时间复杂度:O(n^2);空间复杂度:O(n)

#include<bits/stdc++.h>
using namespace std;
vector<int>vec;
int n,ans1,ans2;
int main()
{
    //建议使用较快的读入、输出方式。
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        vec.push_back(i);//将第i个苹果放进队列。
    while(vec.size()>0)//队列里还有苹果的话
    {
        ans1++;//总操作次数加一
        for(int i=0;i<vec.size();i+=2)//枚举每个要拿掉的苹果
        //本来 i 应该 +3,但是因为每轮循环里都会拿掉掉一个苹果,所以+2
        {
            if(vec[i]==n)//如果要拿掉的苹果编号为 n
                ans2=ans1;
            vec.erase(vec.begin()+i);//删掉该苹果
        }
    }
    printf("%d %d",ans1,ans2);
    return 0;
}

90分做法:

我们发现前面的代码TLE了,因为vector有点慢,我们用普通的数组试试。

代码与之前的十分相似,也是模拟,就不过多做解释了。

#include<bits/stdc++.h>

using namespace std;

int n,total,ans1,ans2,t;
bool a[1000000005];
//a[i]=false表示还没被取走,反之表示被取走了。 
 

int main()
{

	scanf("%d",&n);
	
	total=n;//当前还剩多少苹果。 
	
	while(total)//苹果还有剩 
	{
		ans1++;
		int j=0;//这是每 3 个苹果中的第几个苹果。 
		t=0;//这一轮中删掉了多少苹果。 
		for(int i=1;i<=n;i++)
			if(!a[i])//编号为 i 的苹果还没被取走
			{
				j++;
				j=(j==3?0:j);
				t+=a[i]=(j==1?1:a[i]);
				ans2=(i==n?ans1:ans2);
			} 
		total-=t;
	}
	
	printf("%d %d",ans1,ans2);

	return 0;
}

满分做法:

其实还是很简单的,难度大概就 普及-,其实很好想,只要知道每次删了几个苹果,以及每次有没有删最后一个苹果就行了。这两个加粗的问题用几个数组记录就好了。详见代码。

#include<bits/stdc++.h>

using namespace std;

int n,total,i,ans2,k;

int main()
{

    scanf("%d",&n);
    total=n;//当前剩几个苹果 
    while(total>0)//还有苹果 
    {
        i++;
        if(total%3==1&&k==0)//如果最后一个被取走了 
        {
        	//备注:因为我不知道最后一个苹果还是不是编号为 n 的苹果
			//所以不妨找个数组 k 记一下最后一个苹果还是不是编号为 n 的苹果
            k=1,ans2=i;
        }
		
		//计算还有多少苹果。 
        if(total%3==0)
        {
            total=total/3*2;
        }
        else
        {
            total=total/3*2+(total%3-1);
        }
    }
    printf("%d %d",i,ans2);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值