完全揹包和容斥原理的結合
可以看乙個區間相減的(其實是錯的,但是好理解
求[ 2,
3]
[2,3]
[2,3
]轉換為求
[ 2,
+∞)−
(3,+
∞)⇒[
2,3]
\begin & \;\;[2,+\infty)-(3,+\infty) \\ &\rightarrow[2,3] \end
[2,+∞
)−(3
,+∞)
⇒[2,
3]f[s
]f[s]
f[s]
表示買s
ss的東西有多少種方案(在每種錢都有無限的情況)
f [s
]−∑i
=14f
[s−(
d[i]
+1)∗
c[i]
]f[s]-\sum_^f[s-(d[i]+1)*c[i]]
f[s]−∑
i=14
f[s
−(d[
i]+1
)∗c[
i]]則表示減去這個區間的情況,也就是在錢有限的情況
但是我們不能直接累加起來然後減掉,我們可以看到f[s
−(d[
i]+1
)∗c[
i]
]f[s-(d[i]+1)*c[i]]
f[s−(d
[i]+
1)∗c
[i]]
這是一種錢的情況,因為有可能第1種物品超過限制的同時,第二種物品數量也超過了限制,如果直接累加會把這種情況計算兩次,顯然是不正確的(即同時兩個硬幣有限制的情況減了兩次)。
注意第一種第二種同時超額、第一種第三種都超額、第一種第四種都超額、第二種第三種都超額、第二種第四種都超額、第三種第四種都超額的方案在上一步中都被減了兩次,所以額外都加一次回來
#include
#define ll long long
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using
namespace std;
const
int maxn=
1e6+10;
const
int maxm=
1e3+10;
ll s,n;
ll ans;
ll d[maxn]
,c[maxn]
,f[maxn]
;template
<
class
t>
inline
void
read
(t &x)
while
(isdigit
(ch)
) x*
=f;}
void
pre_work()
}void
dfs(ll pos,ll sum,ll flag)
dfs(pos+
1,sum,flag)
;dfs
(pos+
1,sum-c[pos]
*(d[pos]+1
),-flag);}
void
readdata()
}int
main()
P1450 HAOI2008 硬幣購物
p1450 haoi2008 硬幣購物 完全揹包 容斥 真是秒呀 方案數統計。如果無法直接計算出來,可以嘗試使用容斥原理進行拼湊。你看,這個題中的對答案有影響的元素只有4個。2 n 次方的容斥完全可以做 我們可以使用所有的方案數,減去乙個硬幣不合法的方案數,加上兩個硬幣不合法的方案數,然後如此搞一搞...
題解 P1450 HAOI2008 硬幣購物
本題想到多重揹包還是很容易的 什麼?不知道多重揹包?但是,另一題解已經將時間安排計算地明明白白 所以想到完全揹包 多重揹包跟01揹包似乎區別不大 可以先預處理完全揹包的情況,然後瞎搞容斥原理 不懂容斥原理的看這裡 傳送門 想到完全揹包和容斥原理後,剩下的就只是打表一些簡單的實現了 上 include...
洛谷P1450 HAOI2008 硬幣購物
硬幣購物一共有4種硬幣。面值分別為c1,c2,c3,c4。某人去商店買東西,去了tot次。每次帶di枚ci硬幣,買si的價值的東西。請問每次有多少種付款方法。輸入格式 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s 輸出格式 每次的方法數 輸入樣例 1 1 2 5 ...