a【思维题】山东集训day8T1

T1 A

题目描述

一开始,你拥有一个饼干

现在有三种操作

  1. 一种是将手里的饼干数量 + 1 +1 +1
  2. 一种是将手里的 A A A个饼干换成 1 1 1
  3. 一种是将 1 1 1¥换成 B B B个饼干

求出在 K K K次操作后最多多少饼干

输入格式

一行三个整数, K , A , B K,A,B K,A,B

输出格式

一行一个整数表示答案

样例

输入
4 2 6
输出
7

数据范围

子任务分值ABK
30 A ≤ 10 A\le 10 A10 B ≤ 10 B\le 10 B10 K ≤ 10 K\le 10 K10
30 A ≤ 1 0 4 A\le 10^4 A104 B ≤ 1 0 4 B\le 10^4 B104 K ≤ 1 0 4 K\le 10^4 K104
40 A ≤ 1 0 9 A\le 10^9 A109 B ≤ 1 0 9 B\le 10^9 B109 K ≤ 1 0 9 K\le 10^9 K109

很明显,这是一道思维题。不考数据结构图论动态规划的题都是天使题

让我们来分析一波,就会发现,我们其实有两个方案:

( 1 ) (1) (1)每一次操作都加一块饼干,最后 a n s = k + 1 ans=k+1 ans=k+1

( 2 ) (2) (2)先用 a − 1 a-1 a1次操作将饼干的数量达到 a a a,记录下剩下可操作次数 t = k − a + 1 t=k-a+1 t=ka+1,然后进行捆绑式操作,即用 2 2 2次操作,先将 a a a块饼干换成 1 ¥ 1¥ 1,再用 1 ¥ 1¥ 1换成 b b b块饼干。很容易得出,我们可以用两次操作增加 b − a b-a ba块饼干。如果 t t t为奇数,则最后一次操作就不要将 a a a块饼干换成钱了,毕竟我们要让饼干尽可能的多,所以就用最后一次操作增加一块饼干。

再仔细一想,我们就会发现,有两种情况我们必须使用第一种方案:

( 1 ) k ≤ a (1)k\le a (1)ka 时,你就会惊奇地发现,饼干的数量要么不能达到还钱的数量,要么达到了换钱的数量但是没有多余操作还钱,要么达到了还钱的数量并且有一次操作换钱但是没有多余次数换饼干了。

( 2 ) b ≤ a (2)b\le a (2)ba时,你就会惊奇地发现,就算能用 a a a块饼干换 b b b块饼干,但是要么越换越少要么换了但啥也没变,则时候还不如每次加一块饼干呢。

在剩余情况下,就计算出两个方案能得到的饼干数再取最大值。

好了主要思想就是上边那一堆了。分析过程没有出错, B u t But But,我只有 70 70 70本来以为自己可以100的,结果还是失算了,测评结果是答案错误,且错误的点极其分散,说明是细节性的小问题。再审视一遍自己的代码,我发现判断 k − a + 1 k-a+1 ka+1是否为奇数时我不仅错判成 k k k是否为奇数,而且错判成为偶数时 + + ++ ++,所以能过那些点也是随机的了。由此证明Winnie陈的数据有点小水

先贴上自己 70 70 70分的丑陋代码:

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

ll a,b,k;
ll ans=0;

int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	
	scanf("%lld%lld%lld",&k,&a,&b);
	
	if(a>b+2)ans=k+1;
	else if(k<=a)ans=k+1;
	else{
		ans+=a;
		ans+=((k-a+1)/2)*(b-a);
		if(k%2==0)ans++;//没错就是这里,万恶的错误源头!
	}
	
	printf("%lld",ans);
	
	//fclose(stdin);
	//fclose(stdout);
	
	return 0;
}

然后就是标程,Winnie陈的美丽高级代码,压行看得我着实难受

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define ll long long
ll ans;
int K,A,B;
int main()
{
	// freopen("a.in","r",stdin);
	// freopen("a.out","w",stdout);
	scanf("%d%d%d",&K,&A,&B);
	if(A>=K)return printf("%d\n",K+1),0;
	if(A>=B)return printf("%d\n",K+1),0;
	int t=K-A+1;
	ans=(ll)(t>>1)*(B-A)+(t&1)+A;
	printf("%lld\n",max(K+1ll,ans));
}

还有一个注意点,特别容易遗忘的一点:

一开始的饼干数是1!

接下来就是我自己看看舒服的代码:

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

ll ans;
int K,A,B;

int main(){
	// freopen("a.in","r",stdin);
	// freopen("a.out","w",stdout);
	scanf("%d%d%d",&K,&A,&B);
	
	if(A>=K){
		return printf("%d\n",K+1);
		return 0;
	}
	
	if(A>=B){
		return printf("%d\n",K+1);
		return 0;
	}
	
	int t=K-A+1;
	ans=(ll)(t>>1)*(B-A)+(t&1)+A;//看起来就高级的位运算真令人瑟瑟发抖 
	printf("%lld\n",max(K+1ll,ans));
	
	return 0; 
}

完结撒花!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值