题解:CF413D 2048

· · 题解

题意简述:

给定长度为 n 的序列,将其进行 k 次操作,每次压入一个 2 或者 4,之后以题目中给定的游戏规则,即 2048 游戏规则进行合并,最后要求给出可行的方案数量,使得序列中的最大数大于 2^k

思路分析:

看到这道题的 k 居然如此之,再者要求方案数,优先想到状压

接下来是保姆级的分析。

定义状态:

标准的方式,定义二维,表示压入前 i 个数后情况数为 j

不熟悉状压的可以先去学板子。

初始化:

可以想到,当不压入时,这也是一种合法情况,这时令 dp_{0,0}1 即可。

状态转移:

这是本题的关键所在,应该分两种不同的情况分析。

输出答案:

显然,输出当压入完 n 个数,状态为 2^k 全部选定的情况。

坑点:

代码公示:

#include<bits/stdc++.h>
using namespace std;
const int P=1e9+7;
int n,k;
int x;
int dp[2005][(1<<11)+1];
int a[3005];
signed main(){
    cin>>n>>k;
    dp[0][0]=1;
    for(int i=0;i<n;i++){
        cin>>x;
        for(int j=0;j<=(1<<k);j++){
            if(x!=4){
                int ni=i+1;
                int nj=min((1<<k),j+2);
                dp[ni][nj]=(dp[ni][nj]+dp[i][j])%P;
            }
            if(x!=2){
                int ni=i+1;
                int nj=j+4;
                if(nj==(1<<k)) nj=j;
                if(j&2){
                    nj=4;
                }
                else nj=min(j+4,(1<<k));
                dp[ni][nj]=(dp[ni][nj]+dp[i][j])%P;
            }
        }
    }
    cout<<dp[n][(1<<k)]; 
}