[CF413D]2048

The main idea of ​​the title:
  Fill in the number $2$ or $4$ in an array of length $n(n\le2000)$, after all numbers are filled in, merge to the left according to the rules similar to 2048. Given the numbers on some grids, there are several ways to make the combined maximum number exceed $2^k$ in the current situation.

The idea:
  dynamic programming.
  Define a state as the sum of numbers with the longest non-rising suffix. For example, $(16,4,8,4,4,2)$ corresponds to $18$, because the latter still have the opportunity to merge, and the process of merging can be Directly use addition instead, such as $(16,4,8,4,4,2)$ followed by a $2$, the corresponding state becomes $18+2=20$. Define the target state as $2^k$, and take $\min$ for the state beyond this. Using $f[i][j]$ to represent the number of schemes with the first $i$ lattice state $j$, it is not difficult to obtain the following transition:
  when $x=2$, $f[i][\min( j+2,2^k)]+=f[i-1][j]$;
  when $x=4$ and there is an excess of $2$ at the end, the newly added number cannot be merged with the previous one. , so the previous state is not counted, $f[i][4]+=f[i-1][j]$;
  when $x=4$ and there is no excess $2$ at the end, $f[i ][\min(j+4,2^k)]+=f[i-1][j]$.
  When $x$ is uncertain, the above two transfers can be performed at the same time.
  Time complexity $O(n\cdot2^k)$.

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<algorithm>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 const int K=10,mod=1e9+7;
12 int f[2][(1<<K)+1];
13 int main() {
14     const int n=getint(),k=getint()-1;
15     for(register int i=f[0][0]=1;i<=n;i++) {
16         const int x=getint();
17         std::fill(&f[i&1][0],&f[i&1][1<<k]+1,0);
18         for(register int j=0;j<=1<<k;j++) {
19             if(x!=2) (f[i&1][j&1?2:std::min(j+2,1<<k)]+=f[(i&1)^1][j])%=mod;
20             if(x!=4) (f[i&1][std::min(j+1,1<<k)]+=f[(i&1)^1][j])%=mod;
21         }
22     }
23     printf("%d\n",f[n&1][1<<k]);
24     return 0;
25 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325226017&siteId=291194637