硬幣購物一共有 4
44 種硬幣。面值分別為 c1,
c2,c
3,c4
c_1,c_2,c_3,c_4
c1,c2
,c3
,c4
。某人去商店買東西,去了 tot
totto
t 次。每次帶 dij
d_di
j枚 cij
c_ci
j硬幣,買 s
is_i
si 的價值的東西。請問每次有多少種付款方法。di,
s≤
100000
d_i,s\le 100000
di,s≤
1000
00,t ot
≤1000
tot\le 1000
tot≤10
00。並不會多重揹包,有空再去學,然而多重揹包貌似也不能做。
先考慮沒有限制的情況,就是乙個完全揹包,設已計算出的用前 n
nn 種硬幣購買價值 i
ii 的物品的方案數為 f[i
]f[i]
f[i]
,則僅給第 j
jj 種硬幣加上選取個數滿足 [0,
di,j
][0,d_]
[0,di,
j] 限制時的方案數為 f[i
]−f[
i−c[
j]×(
d[j]
+1)]
f[i]-f[i-c[j]\times(d[j]+1)]
f[i]−f
[i−c
[j]×
(d[j
]+1)
]。為什麼呢?給第 j
jj 種硬幣加上這種限制後使用該種硬幣的數量不得超過 d[j
]d[j]
d[j]
,考慮補集轉化,我們可以先讓它先不使用 d[j
]+
1d[j]+1
d[j]+1
枚該種硬幣,最後再使用 d[j
]+
1d[j]+1
d[j]+1
枚該種金幣,即 f[i
−c[j
]×(d
[j]+
1)
]f[i-c[j]\times(d[j]+1)]
f[i−c[
j]×(
d[j]
+1)]
,這樣無論之前怎麼選都能保證選擇的硬幣個數大於 d[i
]d[i]
d[i]
,最後再用總的方案數減去不滿足條件的方案數就是給第 j
jj 種硬幣加上限制的方案數。
注意到,如果我們給多種硬幣加上限制,可能會有重複減去的部分,即該方案既滿足使用硬幣 x
xx 的數量大於 d[x
]d[x]
d[x]
又滿足使用硬幣 y
yy 的數量大於 d[y
]d[y]
d[y]
,它的方案數等於 f[i
−c[x
]×(d
[x]+
1)−c
[y]×
(d[y
]+1)
]f[i-c[x]\times(d[x]+1)-c[y]\times(d[y]+1)]
f[i−c[
x]×(
d[x]
+1)−
c[y]
×(d[
y]+1
)],將多減的部分加回去就可以了。這實際上使用的是容斥原理,可以用位運算的方法方便的計算出來。
注意要開 64
6464
位整數儲存結果。
#include
typedef
long
long
int ll;
int c[4]
,d[4
];ll f[
100005
],sub[4]
;int
main()
int tot;
scanf
("%d"
,&tot)
;while
(tot--
)int s;
scanf
("%d"
,&s)
;ll ans=0;
for(
int i=
0;i<(1
<<4)
;++i)
if(s-t>=0)
(cnt&1)
?ans-
=f[s-t]
:ans+
=f[s-t];}
printf
("%lld\n"
,ans);}
return0;
}
HAOI2008 硬幣購物
時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 題目描述 硬幣購物一共有4種硬幣。面值分別為c1,c2,c3,c4。某人去商店買東西,去了tot次。每次帶di枚ci硬幣,買si的價值的東西。請問每次有多少種付款方...
HAOI2008 硬幣購物
硬幣購物一共有 4 種硬幣。面值分別為 c 1,c 2,c 3,c 4 某人去商店買東西,去了 tot 次。每次帶 d i 枚 c i 硬幣,買 s i 的價值的東西。請問每次有多少種付款方法。好的,比較欣喜的一點是我們如果不考慮什麼帶了 k i 個,那麼其實就是乙個完全揹包是不是 但是他有乙個特別...
HAOI2008 硬幣購物
題面在這裡 硬幣購物一共有4種硬幣。面值分別為c1,c2,c3,c4。某人去商店買東西,去了tot次。每次帶di枚ci硬幣,買si的價值的東西。請問每次有多少種付款方法。d i,s le 100000,t le 1000 使用單調佇列優化多重揹包十分開心地獲得了20分的好成績 o 4ts 為什麼我就...