1. 程式人生 > 其它 >cf413 D. 2048(dp)

cf413 D. 2048(dp)

題意:

在一個長度為n的陣列中填2或4,待所有數字全部填好後,按照類似於2048的規則向左合併。給定某些格子上的數,問在當前情況下要使得合併後的最大數不小於 \(2^k\) 有幾種填法。

\(n\le 2000,3\le k\le 11\)

思路:

\(f(i,j)\) 表示考慮到第 \(i\) 個數,和為 \(j\) 的方案數。

因為只能填2或4,所以若一個非嚴格遞減的子段末尾有偶數個2,則整個子段可以合併成一個數;若有奇數個2,則末尾的2不能合併。但是加上這個2不影響能否湊到 \(2^k\)

int n, k, f[N][(1<<11)+3];
signed main() {
    iofast;
    cin >> n >> k;
    f[0][0] = 1;
    for(int i = 1; i <= n; i++) {
        int x; cin >> x;
        for(int j = 0; j <= (1<<k); j++) { //列舉上一個的狀態
            if(x != 4) (f[i][min(1<<k,j+2)] += f[i-1][j]) %= mod;
            if(x != 2)
                (f[i][j%4==2 ? 4 : min(1<<k,j+4)] += f[i-1][j]) %= mod;
        }
    }
    cout << f[n][1<<k];
}