其實這道題就按照題面意思直接模擬一下就好喇!
很顯然如果給定硬幣的最小值大於1則輸出"no answer!!!"因為這樣子就無法取到1這個面值了。
先證明一下這一點:如果目前狀態可取前 x
xx **,且當前取了乙個面額為 a
aa 的硬幣,要想構成前 x+a
x + a
x+a 的所有**,必須僅當 x≥a
−1
x \ge a - 1
x≥a−
1 時成立—>
證:若 x
1x < a - 1
x1, 則我們取最小的 x+1
x + 1
x+1,它必須由 x+1
−a
x + 1 - a
x+1−
a 得到,而 x
1x < a - 1
x1,故 x+1
−a
<
0x + 1 - a < 0
x+1−
a<
0,由於不存在小於0的狀態,故原命題成立。
假設當前狀態,前 i
ii 種硬幣已經用最小的硬幣數 ans
ansan
s 構成最大的可行** tot
totto
t ,那麼如果當前 tot
≥ai+
1−
1tot \ge a_ - 1
tot≥ai
+1−
1,那麼就可以直接 i++
i + +
i++;否則累加,使 tot
=tot
+a
itot = tot + a_
tot=to
t+ai
至 tot
≥ai+
1−
1tot \ge a_ - 1
tot≥ai
+1−
1 , 同時每次 ans
ansans++
+++
+ 。因為我們在每一步都滿足 tot
≥ai+
1−
1tot \ge a_ - 1
tot≥ai
+1−
1 , 所以每次 i++
i++i+
+ 時,我們都可以放心操作當前的 tot
+a
itot + a_
tot+ai
操作。特別的,當 i
ii 等於1時,如果 tot
(=0)
−1
tot(=0) < a_ - 1
tot(=0
)−1 , 即 a
1>
1a_ > 1
a1>
1時,不能滿足條件,因而無答案,這裡解釋了第二段的顯然結論。
關於這個累加,由於資料範圍很大,我們很容易被卡(如都是1),所以我們先算出 tot
totto
t 加上多少個 aia_
ai 才能大於等於 ai+
1a_
ai+1
,即個數 k=(
ai+1
−2−t
ot)÷
ai+1
k = (a_ - 2 - tot) \div a + 1
k=(ai+
1−2
−tot
)÷ai
+1,再 tot
=tot
+k∗a
itot = tot + k * a_
tot=to
t+k∗
ai,ans
=ans
+k
ans = ans + k
ans=an
s+k, 用 o(1)的時間解決了問題。同時我們把 an+
1a_
an+1
賦值為 m
mm , 助於判停。
最後注意一點:如果 tot
totto
t 剛好等於 m−1
m - 1
m−1 ,並結束了迴圈,此時我們要在迴圈外輸出 ans
+1
ans + 1
ans+
1 , 以應對此特殊情況。
下面我來貼一下**—>
#include
#include
#define ll long long
#define inf 1023456789
using
namespace std;
ll n, m, a[
2000005
], ans, tot;
intmain()
a[n +1]
= m;
for(
int i =
1; i <= n; i++)}
}printf
("%lld\n"
,ans +1)
;return0;
}
洛谷P2001硬幣的面值
題目傳送門 真是個毒瘤題 一開始想這是乙個多重揹包板子題,於是不假思索打了上去,樣例沒過,再一看題,原來不是 又眼瞎了 於是再次認真讀題 很顯然我們可以發現 如果給定硬幣最小面額大於1,那麼就一定輸出no answer!因為首先 為1的就組成不了。接著思考,假設第i種硬幣已用最小硬幣數ans組成最大...
洛谷 P2708 硬幣翻轉
時間限制1.00s 記憶體限制125.00mb 從前有很多個硬幣擺在一行,有正面朝上的,也有背面朝上的。正面朝上的用1表示,背面朝上的用0表示。現在要求從這行的第乙個硬幣開始,將前若干個硬幣一起翻面,問如果要將所有硬幣翻到正面朝上,最少要進行這樣的操作多少次?乙個字串,由0和1組成,表示硬幣狀態 乙...
洛谷P1146 硬幣翻轉
時間限制 1.00s 記憶體限制 125.00mb 題目描述在桌面上有一排硬幣,共nn枚,每一枚硬幣均為正面朝上。現在要把所有的硬幣翻轉成反面朝上,規則是每次可翻轉任意n 1n 1枚硬幣 正面向上的被翻轉為反面向上,反之亦然 求乙個最短的操作序列 將每次翻轉n 1枚硬幣成為一次操作 輸入格式 乙個自...