1. 程式人生 > 其它 >LuoguP6188 [NOI Online #1 入門組] 文具訂購 題解

LuoguP6188 [NOI Online #1 入門組] 文具訂購 題解

LuoguP6188 [NOI Online #1 入門組] 文具訂購 題解

Content

小明想用 \(n\) 塊錢購買 \(3\) 個物品:

  • 圓規,每個7塊。
  • 筆,每支4塊。
  • 筆記本,每本3塊。

同時,他還有3個要求:
設圓規、筆、筆記本購買的數量分別是 \((a,b,c)\),則:

  1. \(n\)塊錢必須全部花完,即 \(7a+4b+3c=n\)
  2. 在滿足第一個要求的前提下,成套的數目最大,即滿足 \(\min{(a,b,c)}\) 為最大值。
  3. 在滿足第二個要求的前提下,總數量最大,即滿足 \(a+b+c\) 儘量大。

此時的最優解僅有一個,請求出這個最優解。

資料範圍:\(0\leqslant n\leqslant 10^5\)

Solution

來個更暴力的。

\(x=n\div 14,y=n\bmod 14\),最優解為 \((a_0,b_0,c_0)\)。(這裡的 \(\div\) 指整除)

我們直接可以根據\(y\)進行分類討論:

  1. \(y=0\),此時正好成套,此時 \((a_0,b_0,c_0)=(x,x,x)\)
  2. \(y=1\),那這樣子怎麼辦?沒法再買了。沒關係,騰出一個 \(14\) 元不行嗎?當然,如果恰好只有 \(1\) 塊錢,那就真的無解了。否則,騰出一個 \(14\) 元來,套數減 \(1\),這時剩下的錢數變成了 \(15\) 元。因為這已經是成套數目最大的情況了,所以此時我們設法將總數量最大化,即儘量買花錢少的物品。我們欣喜地發現,在這個情況中,剩下 \(15\)
    塊錢正好可以買 \(5\) 個筆記本,所以此時 \((a_0,b_0,c_0)=(x-1,x-1,x+4)\)
  3. \(y=2\),跟 \(y=1\) 時的做法類似,也是騰出 \(14\) 塊錢。此時剩下 \(16\) 塊錢,我們發現,最優方案此時是再購買 \(4\) 個筆記本,\(1\) 支筆。所以此時 \((a_0,b_0,c_0)=(x-1,x,x+3)\)。當然如果正好只有 \(2\) 塊錢的話就真的無解了。
  4. \(y=3\),正好可以買 \(1\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x,x+1)\)
  5. \(y=4\),正好可以買 \(1\) 支筆,此時 \((a_0,b_0,c_0)=(x,x+1,x)\)
  6. \(y=5\),跟 \(y=1\)\(y=2\) 時的做法類似,騰出 \(14\) 元后就有了 \(19\) 元,此時正好可以買 \(5\) 本筆記本,\(1\) 支筆,所以 \((a_0,b_0,c_0)=(x-1,x,x+4)\)。當然如果正好只有 \(5\) 塊錢的話就真的無解了。
  7. \(y=6\),正好可以買 \(2\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x,x+2)\)
  8. \(y=7\),正好可以買 \(1\) 支筆,\(1\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x+1,x+1)\)
  9. \(y=8\),正好可以買 \(2\) 支筆,此時 \((a_0,b_0,c_0)=(x,x+2,x)\)
  10. \(y=9\),正好可以買 \(3\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x,x+3)\)
  11. \(y=10\),正好可以買 \(1\) 支筆,\(2\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x+1,x+2)\)
  12. \(y=11\),正好可以買 \(2\) 支筆,\(1\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x+2,x+1)\)
  13. \(y=12\),正好可以買 \(4\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x,x+4)\)
  14. \(y=13\),正好可以買 \(1\) 支筆,\(3\) 本筆記本,此時 \((a_0,b_0,c_0)=(x,x+1,x+3)\)

所有情況都討論完了。
沒錯,完了。
接下來奉上最暴力的程式碼。

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;

int n, a, b, c;
//成套的數目儘量大,所以儘量多買14元 

int main() {
	scanf("%d", &n);
	int p = n / 14;
	switch(n % 14) {
		case 0: {
//			if(!p)	printf("-1");
			printf("%d %d %d", p, p, p);
			break;
		}
		case 1: {
			if(n < 14)	printf("-1");
			else	printf("%d %d %d", p - 1, p - 1, p + 4);
			break;
		}
		case 2: {
			if(n < 14)	printf("-1");
			else	printf("%d %d %d", p - 1, p, p + 3);
			break;
		}
		case 3: {
			printf("%d %d %d", p, p, p + 1);
			break;
		}
		case 4: {
			printf("%d %d %d", p, p + 1, p);
			break;
		}
		case 5: {
			if(n < 14)	printf("-1");
			else	printf("%d %d %d", p - 1, p, p + 4);
			break;
		}
		case 6: {
			printf("%d %d %d", p, p, p + 2);
			break;
		}
		case 7: {
			printf("%d %d %d", p, p + 1, p + 1);
			break;
		}
		case 8: {
			printf("%d %d %d", p, p + 2, p);
			break;
		}
		case 9: {
			printf("%d %d %d", p, p, p + 3);
			break;
		}
		case 10: {
			printf("%d %d %d", p, p + 1, p + 2);
			break;
		}
		case 11: {
			printf("%d %d %d", p, p + 2, p + 1);
			break;
		}
		case 12: {
			printf("%d %d %d", p, p, p + 4);
			break;
		}
		case 13: {
			printf("%d %d %d", p, p + 1, p + 3);
			break;
		}
	}
	return 0;
}