bzoj 3195: [Jxoi2012]奇怪的道路
阿新 • • 發佈:2018-10-31
連結:3195: [Jxoi2012]奇怪的道路
- 大意:給定\(n\),\(m\),\(k\),求出滿足下列兩個要求的圖的個數,允許重邊己環和不聯通:
- 每條邊\(1<=|u-v|<=K\)且每個點連邊偶數。$n,m\leq 30 \(,\)k\leq 8$
- 有個樸素的\(Dp\)就是狀壓\(k\),設\(f_{i,j,s}\)表示前\(i\)個點,\(j\)條邊,最後\(k\)個點的奇偶性為\(s\)的方案數。
- 然後列舉\(i\)和誰連邊向\(j+1\)轉移,每個\(s\)再向\(i+1\)轉移。
- 寫完後發現這個做法有\(bug\),因為同一個狀態因為\(i\)
- 其實很好解決,\(i\)連向相同一個點的邊就很像揹包問題中的一件物品,每一件物品都是不限量的(只是最終要求了奇偶)。
- 想一想,我們的完全揹包統計方案時並沒有多開一維,但絕對不會重複計數的。
- 原因很簡單,在做揹包問題時,各個物品的選取存在嚴格順序,不存在選了幾個物品\(a\),又選了一點別的,再去選了幾個物品\(a\)的情況。
- 所以這裡應當嚴格區分出各個物品,在每一個物品內部做完全揹包。
- 程式碼很短
#include<bits/stdc++.h> #define R register int using namespace std; const int mod=1000000007; int n,m,k,now,lm,f[2][35][600]; void add(R &x,R y){x=(x+y>=mod?x+y-mod:x+y);} int main(){ freopen("s.in","r",stdin); cin>>n>>m>>k,lm=(1<<(k+1)),f[now][0][0]=1; for(R i=1;i<=n;++i){ now^=1,memset(f[now],0,sizeof(f[now])); for(R j=0;j<=m;++j) for(R S=0;S<(1<<k);++S) f[now][j][S<<1]=f[now^1][j][S]; for(R p=1;p<=min(i-1,k);++p) for(R j=0;j<=m;++j) for(R S=0;S<lm;++S) add(f[now][j+1][S^1^(1<<p)],f[now][j][S]); } cout<<f[now][m][0]; return 0; }