時間限制:(每個case)2s 空間限制:128mb
小q十分富有,擁有非常多的硬幣,小q擁有的硬幣是有規律的,對於所有的非負整數k,小q恰好各有兩個面值為2^k的硬幣,所以小q擁有的硬幣就是1,1,2,2,4,4,8,8,…。小q有一天去商店購買東西需要支付n元錢,小q想知道有多少種方案從他擁有的硬幣中選取一些拼湊起來恰好是n元(如果兩種方案某個面值的硬幣選取的個數不一樣就考慮為不一樣的方案)。
輸入:輸入包括乙個整數n(1<=n<=10^18),表示小q需要支付多少錢。注意n的範圍。
輸出:輸出乙個整數,表示小q可以拼湊出n元錢放的方案數。
樣例輸入:6
樣例輸出:3
這道題可以用動態規劃來做,只是狀態轉移方程比較難想,動態規劃是乙個填表的過程,首先需要確定表是1維陣列還是二維陣列,嘗試1維陣列基本上不可行,直接從二維表入手,建立二維陣列res
,其中行數為n+1,列數為硬幣的種數(不超過log
2(n)
log_2(n)
log2(
n)),res[i][j]
表示使用j
種硬幣組合出i
元的方案數,由於每種硬幣可以使用0、1、2次,假設使用m
次,則剩餘rest = i - (2^j) * m
元,若rest>=0
則只需要知道使用前j-1
種硬幣組合出rest
的方案數,即res[rest][j-1]
,若rest<0
,則表明不能使用m
次,因為會超出i
元。因此可以得到狀態轉移方程為:
r es
[i][
j]=r
es[i
−2j∗
0][j
−1]+
res[
i−2j
∗1][
j−1]
+res
[i−2
j∗2]
[j−1
]res[i][j] = res[i-2^j*0][j-1] + res[i-2^j*1][j-1] + res[i-2^j*2][j-1]
res[i]
[j]=
res[
i−2j
∗0][
j−1]
+res
[i−2
j∗1]
[j−1
]+re
s[i−
2j∗2
][j−
1]在實現時注意特殊情況,res[0,j] = 1,res[1,j] = 1,以及res[2,j] = 1(使用兩個1元硬幣可以組合出2,因此方案數為1)
public
class
main
// 動態規劃的二維陣列含義 res[i][j]: 只用前j種硬幣組合出i元的方案數
// 狀態轉移方程:res[i][j] = res[i-2^j*0][j-1] + res[i-2^j*1][j-1] + res[i-2^j*2][j-1]
// 因為每種硬幣可以被使用0、1、2次,三種情況對應的剩餘元數即i-2^j*0、i-2^j*1、i-2^j*2
// 為什麼是j-1? 因為res[i][j]表示現在才用第j種硬幣
for(
int i =
2; i < n +
1; i++)}
return res[n]
[coinnum -1]
;}public
static
void
main
(string[
] args)
}
騰訊機試題1
小q打算穿越怪獸谷,他不會打怪,但是他有錢。他知道,只要給怪獸一定的金幣,怪獸就會一直護送他出谷。在谷中,他會一次遇見n只怪獸,每只怪獸都有自己的武力值和要 賄賂 它所需的金幣。如果小q沒有 賄賂 它而它的武力值又高於護送小q的所有怪獸的武力值之和,這只怪獸就會攻擊小q 小q想知道,要想成功穿越怪獸...
騰訊機試題2
題目描述 小q在進行乙個對數字進行拆分的遊戲,遊戲規則如下 小q最初只有乙個整數n,接下來每一輪中,小q被允許對現有的每個數進行下面兩個操作之一 但是拆分操作只允許使用至多k次,現在小q想知道把n完全消去需要多少輪操作。輸入描述 輸入一行包含兩個整數n,k 1 n 100,0 k 100 輸出描述 ...
硬幣拼湊(01揹包和完全揹包)
有n1 n2種面值的硬幣,其中前n1種為普通幣,可以取任意枚,後n2種為紀念幣,每種最多只能取一枚,每種硬幣有乙個面值,問能用多少種方法拼出m的面值?輸入描述 第一行輸入三個整數n1,n2,m n1,n2 1000 m 100000 第二行輸入n1個整數表示普通幣的面值 第三行輸入n2個整數表示紀念...