1. 程式人生 > >bzoj3195 [Jxoi2012]奇怪的道路

bzoj3195 [Jxoi2012]奇怪的道路

奇怪 ret 正在 rep 高度 += 網絡 for return

Description

小宇從歷史書上了解到一個古老的文明。這個文明在各個方面高度發達,交通方面也不例外。考古學家已經知道,這個文明在全盛時期有 \(n\) 座城市,編號為 \(1\cdots n\)\(m\) 條道路連接在這些城市之間,每條道路將兩個城市連接起來,使得兩地的居民可以方便地來往。一對城市之間可能存在多條道路。

據史料記載,這個文明的交通網絡滿足兩個奇怪的特征。首先,這個文明崇拜數字 \(K\) ,所以對於任何一條道路,設它連接的兩個城市分別為 \(u\)\(v\) ,則必定滿足 \(1 \le |u - v| \le K\) 。此外,任何一個城市都與恰好偶數條道路相連( \(0\)

也被認為是偶數)。不過,由於時間過於久遠,具體的交通網絡我們已經無法得知了。小宇很好奇這 \(n\) 個城市之間究竟有多少種可能的連接方法,於是她向你求助。

方法數可能很大,你只需要輸出方法數模 \(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]奇怪的道路