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];
}
posted @ 2022-03-18 12:05  Bellala  阅读(28)  评论(0)    收藏  举报