a【思維題】山東集訓day8T1

T1 A

題目描述

一開始,你擁有一個餅乾

現在有三種操作

  1. 一種是將手裏的餅乾數量+1+1
  2. 一種是將手裏的AA個餅乾換成11
  3. 一種是將11¥換成BB個餅乾

求出在KK次操作後最多多少餅乾

輸入格式

一行三個整數,K,A,BK,A,B

輸出格式

一行一個整數表示答案

樣例

輸入

4 2 6

輸出

7

數據範圍

子任務分值 A B K
30 A10A\le 10 B10B\le 10 K10K\le 10
30 A104A\le 10^4 B104B\le 10^4 K104K\le 10^4
40 A109A\le 10^9 B109B\le 10^9 K109K\le 10^9

很明顯,這是一道思維題。不考數據結構圖論動態規劃的題都是天使題

讓我們來分析一波,就會發現,我們其實有兩個方案:

(1)(1)每一次操作都加一塊餅乾,最後ans=k+1ans=k+1

(2)(2)先用a1a-1次操作將餅乾的數量達到aa,記錄下剩下可操作次數t=ka+1t=k-a+1,然後進行捆綁式操作,即用22次操作,先將aa塊餅乾換成11¥,再用11¥換成bb塊餅乾。很容易得出,我們可以用兩次操作增加bab-a塊餅乾。如果tt爲奇數,則最後一次操作就不要將aa塊餅乾換成錢了,畢竟我們要讓餅乾儘可能的多,所以就用最後一次操作增加一塊餅乾。

再仔細一想,我們就會發現,有兩種情況我們必須使用第一種方案:

(1)ka(1)k\le a 時,你就會驚奇地發現,餅乾的數量要麼不能達到還錢的數量,要麼達到了換錢的數量但是沒有多餘操作還錢,要麼達到了還錢的數量並且有一次操作換錢但是沒有多餘次數換餅乾了。

(2)ba(2)b\le a時,你就會驚奇地發現,就算能用aa塊餅乾換bb塊餅乾,但是要麼越換越少要麼換了但啥也沒變,則時候還不如每次加一塊餅乾呢。

在剩餘情況下,就計算出兩個方案能得到的餅乾數再取最大值。

好了主要思想就是上邊那一堆了。分析過程沒有出錯,ButBut,我只有7070本來以爲自己可以100的,結果還是失算了,測評結果是答案錯誤,且錯誤的點極其分散,說明是細節性的小問題。再審視一遍自己的代碼,我發現判斷ka+1k-a+1是否爲奇數時我不僅錯判成kk是否爲奇數,而且錯判成爲偶數時++++,所以能過那些點也是隨機的了。由此證明Winnie陳的數據有點小水

先貼上自己7070分的醜陋代碼:

#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; 
}

完結撒花!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章