Ex - E or m Editorial by en_translator
Consider the following DP (Dynamic programming): \(dp[\) \(i\) \(][\) set of columns where all squares are painted \(] = \{\) number of ways to paint the first \(i\) lines \(\}\).
Specifically, each way of painting corresponds to the keys as follows:
1101 0111 1111
1111 0001 0011
1001 1110 1101
dp [3][1001] [3][0000] [3][0001]
Let’s consider the transition of this DP.
For example, dp[5][1101001]
can transition to:
dp[6][sssssss]
by placing ( subset of1101001
) =sssssss
;dp[6][110ssss]
by placing111
+ ( subset of1001
) =111ssss
;dp[6][11010ss]
by placing11111
+ ( subset of01
) =11111ss
; anddp[6][110100s]
by placing111111
+ ( subset of1
) =111111s
.
As you can see, the transitions can be disjointly and fully classified by fixing the first occurrence of 0
in the key and letting the latter part be a subset of the key.
The transition to subsets can be done in the manner of Fast Zeta Transform.
(*) Note that the area of 1
s expands from left, so one can apply the “transition to subsets” only once to finish the transitions by performing the transitions for \(k\) 1
s in ascending order of \(k\), while, before every step, updating the DP table to represent the transitions of placing “(\(k\) 1
s) + (subset of the others)”. (For more details, see the sample code.)
Now, the problem has been solved if the input grid is all ?
. What if some of the squares are specified?
It is still not very difficult. As we described above, we know what to place in the row, so we can do the transitions only for those we can place.
For example, when applying a transition on a subset, if 1
cannot be placed, then the 1
in the key always transitions to 0
; if 0
cannot be placed, the transition is impossible if the key is 0
, and 1
is always placed if the key is 1
.
The (*) paragraph can be achieved by placing \(k\) consecutive 1
s from the left only when it is allowed.
Again, for more details, see the sample code.
This way, the time complexity of \(O(2^M NM)\) is achieved, and you can solve this problem.
Sample code (C++):
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
int main(){
int n,m;
cin >> n >> m;
vector<string> s(n);
for(auto &nx : s){cin >> nx;}
vector<long long> dp(1<<m,0);
dp[(1<<m)-1]=1;
for(int i=0;i<n;i++){
vector<long long> ndp=dp;
for(int j=0;j<m;j++){
vector<long long> work(1<<m,0);
if(s[i][j]!='1'){
// put 0
for(int k=0;k<(1<<m);k++){
if(k&(1<<j)){
work[k^(1<<j)]+=ndp[k];
work[k^(1<<j)]%=mod;
}
else{
work[k]+=ndp[k];
work[k]%=mod;
}
}
}
if(s[i][j]!='0'){
// put 1
for(int k=0;k<(1<<m);k++){
if(k&(1<<j)){
work[k]+=ndp[k];
work[k]%=mod;
}
}
}
ndp=work;
bool ok=true;
for(int k=0;k<=j;k++){
if(s[i][k]=='0'){ok=false;break;}
}
if(!ok){continue;}
for(int k=0;k<(1<<m);k++){
if(k&(1<<j)){continue;}
ndp[k]+=dp[k];
ndp[k]%=mod;
}
}
dp=ndp;
}
long long res=0;
for(auto &nx : dp){res+=nx;res%=mod;}
cout << res << "\n";
return 0;
}
posted:
last update: