狀壓[Jxoi2012]奇怪的道路
阿新 • • 發佈:2018-11-02
小宇從歷史書上了解到一個古老的文明。這個文明在各個方面高度發達,交通方面也不例外。考古學家已經知道,這個文明在全盛時期有n座城市,編號為1…n。m條道路連線在這些城市之間,每條道路將兩個城市連線起來,使得兩地的居民可以方便地來往。一對城市之間可能存在多條道路。
據史料記載,這個文明的交通網路滿足兩個奇怪的特徵。首先,這個文明崇拜數字K,所以對於任何一條道路,設它連線的兩個城市分別為u和v,則必定滿足1 <=|u - v| <= K。此外,任何一個城市都與恰好偶數條道路相連(0也被認為是偶數)。不過,由於時間過於久遠,具體的交通網路我們已經無法得知了。小宇很好奇這n個城市之間究竟有多少種可能的連線方法,於是她向你求助。
方法數可能很大,你只需要輸出方法數模1000000007後的結果。
觀察到K較小可以狀態壓縮
而且狀態也好定義:
前
個城市用了
條邊當前
條邊奇偶性情況。
但是發現不好補表,因為你要計算字首和關係,考慮刷表法用當前狀態更新後來狀態
但是注意算重問題:
即你要列舉連向哪一條邊,這本質是讓統計有序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
LL mod=1000000007;
LL F[32][32][(1<<9)];
int n,m,k;
int main(){
cin>>n>>m>>k;
F[1][0][0]=1;
for(int i=1;i<=n;++i){
for(int l=max(1,i-k);l<i;++l){
for(int j=0;j<=m;++j){
for(int S=0;S<=min((1<<(k+1))-1,(1<<i)-1);++S){
int T=S^(1<<(i-l))^1;
F[i][j+1][T]=(F[i][j][S]+F[i][j+1][T])%mod;
}
}
}
for(int j=0;j<=m;++j){
for(int S=0;S<=min((1<<(k+1))-1,(1<<i)-1);++S){
if(S&(1<<k)){continue;}
F[i+1][j][(S<<1)%(1<<(k+1))]=(F[i+1][j][(S<<1)%(1<<(k+1))]+F[i][j][S])%mod;
}
}
}
cout<<F[n][m][0];
return 0;
}