kuangbin 專題一:簡單搜尋 非常可樂

2020-10-01 14:00:23

題目連結:
傳送門

#include<cstdio>
using namespace std;

int gcd(int a,int b) {
	return !b ? a : gcd(b,a%b);
}
int main() {
	int s, n, m;
	while(scanf("%d%d%d",&s,&n,&m)) {
		if(s == 0 && n== 0 && m== 0) break;
		s/=gcd(n,m);
		if(s % 2 != 0)printf("NO\n");
		else printf("%d\n",s-1);
	}
	return 0;
}

這道是首先第一反應可以用bfs做,bfs的具體方法就是列舉abc間倒來倒去的操作總共六個,然後記錄狀態與前面pots(如果你是刷kaungbin提單刷到這道題)的操作相似。但這裡我想講的是一種數論的做法

數論涉及到的知識點是exgcd相關題目
具體思路大致如下:
首先我們設兩個小瓶子容積分別為a,b,問題轉化成通過兩個小瓶子的若干次倒進或倒出操作得到(a+b)/2體積的可樂,設兩個小瓶子被操作x次和操作x次;那麼此時問題就轉換為求ax+by=(a+b)/2的不定方程,不定方程的具體求法可以參考上方那個連結。首先通過exgcd求出x和y的一個特解,然後通過特解求出同解。在通解中我們要選擇一個x+y儘可能小的解。此時我們可以通過特解推出這個解為(c+d)/2.通過x和y的通解形式顯然可以看出x和y一正一負,不妨設x<0,那麼就是往第一個小瓶子倒進x次,第二個小瓶子倒出y次,但是由於瓶子容積有限,所以倒進倒出操作都是通過大瓶子來解決的,一次倒進操作後為了繼續使用小瓶子還要將小瓶子中可樂倒回大瓶子中,倒出操作同理,所以總操作次數是(c+d)/2*2=c+d,但是注意最後剩下的(a+b)/2體積的可樂一定是放在兩個小瓶子中較大的那個中,而不是再倒回到大瓶子中,所以運算元要減一。

詳細的推導過程請看某數學大佬的部落格