time limit: 10 sec memory limit: 128 mb
[submit][status][discuss]
ftiasch 有 n 個物品, 體積分別是 w1
, w2
, ..., wn
。由於她的疏忽, 第 i 個物品丟失了.
「要使用剩下的 n - 1 物品裝滿容積為 x 的揹包,有幾種方法呢?」 -- 這是經典的問題了。
她把答案記為 count(i, x) ,想要得到所有1 <= i <= n, 1 <= x <= m的 count(i, x) **。
第1行:兩個整數 n 和 m ,物品的數量和最大的容積。
第2行: n 個整數 w1
, w2
, ..., wn
, 物品的體積。
乙個 n × m 的矩陣, count(i, x)的末位數字。
3 21 1 2
1111
211 ≤ n ≤ 2 × 1e3, 1 ≤ m ≤ 2 × 1e3
首先,我們發現,對於l,r:
去掉l,就是要用[1, l - 1]∪[l + 1, n]的物品來求解;
去掉r,就是要用[1, r - 1]∪[r + 1, n]的物品來求解。
若是我們更新完了([1, l - 1]∪[l + 1, n])∩([1, r - 1]∪[r + 1, n])的部分,
再加上l的,即是去掉r的答案;再加上r的,即是去掉l的答案。
那麼我們就可以考慮分治:
設計狀態solve(l, r),表示已經做完了[1, l - 1]∪[r + 1, n]時的答案。
然後二分乙個mid = l + r >> 1;
要處理[l, mid]則將[mid + 1, r]的更新一下,反之同理。
那麼這樣我們最後做到l == r時候,顯然就是去掉l的答案了。
dp部分顯然就是乙個簡單的揹包。
1 #include2 #includeview code3 #include4 #include5 #include6 #include7 #include8 #include9
using
namespace
std;
10 typedef long
long
s64;
1112
const
int one = 100005;13
const
int inf = 2147483640;14
15int
n, m;
16int
a[one];
17int f[20
][one];
1819
intget
()20
2930
void solve(int l, int r, int
dep)
3139
40int mid = l + r >> 1;41
42for(int j = m; j >= 0; j--) f[dep + 1][j] =f[dep][j];
43for(int i = mid + 1; i <= r; i++)
44for(int j = m; j >= 0; j--)
45 (f[dep + 1][j] += f[dep + 1][j - a[i]]) %= 10
;46 solve(l, mid, dep + 1
);47
48for(int j = m; j >= 0; j--) f[dep + 1][j] =f[dep][j];
49for(int i = l; i <= mid; i++)
50for(int j = m; j >= 0; j--)
51 (f[dep + 1][j] += f[dep + 1][j - a[i]]) %= 10
;52 solve(mid + 1, r, dep + 1
);53}54
55int
main()
56
BZOJ2287消失之物
dpdpdpdpdpdpdpdp 討厭dp 這道題看起來很難 實際上也很難 思路 我們要求拿走一件物品之後的方案數,那麼肯定會涉及到不拿走的情況,那麼不拿走的情況是什麼呢?用前i件物品拼成體積j的方案數,所以我們要先預處理一下這個初始陣列f i 也就是一件都不拿走的情況 之後呢?我們考慮如何轉移拿走...
BZOJ 2287 消失之物 線段樹分治 揹包
time limit 10 sec memory limit 128 mb submit 875 solved 499 submit status discuss ftiasch 有 n 個物品,體積分別是 w1 w2 wn 由於她的疏忽,第 i 個物品丟失了。要使用剩下的 n 1 物品裝滿容積為 ...
BZOJ 2287 消失之物 揹包DP
本來在寫暴力,寫著寫著突然就想到了這種做法 希望今年noi pnoip noip 的時候也能這樣 先不考慮某個物品消失的情況,也就是樸素的01揹包 rep i,1,n repd j,m,v i f j add f j f j v i 然後考慮第i ii物品消失之後,對答案的影響就是多了沒消失之前的累...