for (int i=1; i<=n; ++i) if (!ind[i]) q.push(i); while (!q.empty()) { int now=q.top(); q.pop(); printf("%d ", now); for (int k=head[now]; k; k=nex[k]) if (--ind[to[k]]==0) q.push(to[k]); }
現有 \(N\) 個物品和容積爲 \(M\) 的揹包. 物品的體積分別爲 \(V_1, V_2, ..., V_N\). 求不選取物品 \(i\) 時, 裝滿揹包的方案數量.spa
設 \(f(n, V)\) 爲正向枚舉的揹包, \(g(n, V)\) 爲反向枚舉的揹包, 則方案數爲 \(\displaystyle \sum_{i=1}^{n}\sum_{j=0}^{m} f(i-1, j)\cdot g(i+1, m-j)\).code
本次錯誤在於沒有搞明白1維和2維揹包的代碼異同點:1維揹包已經無需直接賦值,2維揹包仍是須要 \(f(i, j)=f(i-1, j)\) 的。排序
#include <cstdio> int n, m, w[1003], f[1003][10003], g[1003][10003], ans; int main() { scanf("%d%d", &n, &m); for (int i=1; i<=n; ++i) scanf("%d", &w[i]); f[0][0]=1; for (int i=1; i<=n; ++i) { for (int j=m; j>=w[i]; --j) f[i][j]=(f[i-1][j]+f[i-1][j-w[i]])%1014; for (int j=w[i]-1; ~j; --j) f[i][j]=f[i-1][j]; // (*) } g[n+1][0]=1; for (int i=n; i; --i) { for (int j=m; j>=w[i]; --j) g[i][j]=(g[i+1][j]+g[i+1][j-w[i]])%1014; for (int j=w[i]-1; ~j; --j) g[i][j]=g[i+1][j]; // (*) } for (int i=1; i<=n; ++i) { ans=0; for (int j=0; j<=m; ++j) ans=(ans+f[i-1][j]*g[i+1][m-j])%1014; printf("%d ", ans); } return 0; }
給出數列 \(\{A_n\}\), 修改最少的元素, 使得數列 \(\{A_n\}\) 成爲一個公差爲 1 的等差數列.io
預處理成數列 \(\{A_n-n\}\) 便可極大簡化本題解法.class