bzoj3195 [Jxoi2012]奇怪的道路
Description
小宇從歷史書上了解到一個古老的文明。這個文明在各個方面高度發達,交通方面也不例外。考古學家已經知道,這個文明在全盛時期有 \(n\) 座城市,編號為 \(1\cdots n\) 。 \(m\) 條道路連接在這些城市之間,每條道路將兩個城市連接起來,使得兩地的居民可以方便地來往。一對城市之間可能存在多條道路。
據史料記載,這個文明的交通網絡滿足兩個奇怪的特征。首先,這個文明崇拜數字 \(K\) ,所以對於任何一條道路,設它連接的兩個城市分別為 \(u\) 和 \(v\) ,則必定滿足 \(1 \le |u - v| \le K\) 。此外,任何一個城市都與恰好偶數條道路相連( \(0\)
方法數可能很大,你只需要輸出方法數模 \(1000000007\) 後的結果。
Input
輸入共一行,為 \(3\) 個整數 \(n,m,K\) 。
Output
輸出 \(1\) 個整數,表示方案數模 \(1000000007\) 後的結果。
Sample Input
Case: 1
3 4 1
Case: 2
4 3 3
Sample Output
Case: 1
3
Case: 2
4
HINT
\(100\%\) 的數據滿足 \(1 \le n \le 30, 0 \le m \le 30, 1 \le K \le 8\)
Solution
狀壓吼題。
發現 \(K\) 很小,於是考慮壓一波 \(K\) 。
\(f[i][j][k][l]\) 表示正在考慮點 \(i\) ,已經連了 \(j\) 條邊, 點 \(i - K\) 到 點 \(i\) 的度數狀態為 \(k\) ,正在考慮點 \(i-K+l\) 與點 \(i\) 的連邊。最終答案為 \(f[n+1][m][0][0]\)
考慮轉移 \[f[i][j][k][l]\to \begin{Bmatrix}f[i][j][k][l+1] \\ f[i][j+1][k\oplus (1<<K) \oplus (1<<l)][l] \end{Bmatrix}\]
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define rep(i, a, b) for (int i = a; i <= b; i++)
int f[40][40][1 << 9][9], n, m, K, bin[10] = { 1 };
int main() {
rep(i, 1, 10) bin[i] = bin[i - 1] << 1;
cin >> n >> m >> K;
f[2][0][0][0] = 1;
rep(i, 2, n) rep(j, 0, m) rep(k, 0, bin[K + 1] - 1) {
rep(l, 0, K - 1) if (f[i][j][k][l]) {
(f[i][j][k][l + 1] += f[i][j][k][l]) %= mod;
if (i - K + l > 0 && j < m) (f[i][j + 1][k ^ bin[l] ^ bin[K]][l] += f[i][j][k][l]) %= mod;
}
if (!(k & 1) && f[i][j][k][K]) f[i + 1][j][k >> 1][0] = f[i][j][k][K];
}
cout << f[n + 1][m][0][0];
return 0;
}
bzoj3195 [Jxoi2012]奇怪的道路