Educational Codeforces Round 107 (Rated for Div. 2) E Colorings and Dominoes

题目传送门

题意:

  给一个n*m的矩阵, 'o' 表示可以将此格子变成 蓝格子 或 红格子 . 在一行中两个相邻的蓝格子可以放置一个 1*2 的矩阵块 ,在一列中两个相邻的红格子可以放置一个 1*2 的矩阵块. 求所有方案中可以放置1*2矩阵块的最大数量.每种方案都是放置矩阵块最优的.

思路:

  可以确定,行和列的贡献是互不干扰的.所以可以先分析出 所有行所产生的贡献

  设一段连续的 'o' 产生的本质贡献是 p, 'o'的数量是cnt .   矩阵中'o'的数量是 sum ;

  对于一行中连续的一段'o', 其他所有的'o'是不会对这一段产生的本质贡献 p 产生干扰,也就是说除了这一段的'o',其他的'o'是可以随意变换的.

  那么这一段'o'所产生的总贡献是  p*pow(2,sum-cnt); 

  现在问题就转化成了 求一段连续的'o'的贡献

  设dp[i] 为 长度为 i 的'o'所有方案可以放置的矩阵总数

  假设现在有长度为 4 的'o' : oooo 求dp[5]

  //为了表示方便,0 代表将'o' 变成红格子, 1代表将'o'变成蓝格子 11就表示可以放一个1*2矩阵

  若我们将第五个格子变成'0'  即 oooo0 ,并不会对先前已产生的方案数造成影响,加上即可==> +dp[i-1]

  若我们将第五个格子变成'1'  即oooo1  ,此时若第4个格子为1,那么会产生新的方案.需要将4,5号格子看成一体(并不会影响最优放置).将4,5号格子看成一体后,4号格子就有两种情况,就需要加上2倍的dp[i-2] ==>+2*dp[i-2]

  若4,5号格子为(1,1) 我们还需要计算(1,1)产生的贡献,即 pow(2,cnt-2) //前3个格子随意选择 

  递归方程为 : dp[i]=dp[i-1]+dp[i-2]*2+pow(2,i-2);

参考代码:

 1 #include<bits/stdc++.h>
 2 #define ll long long 
 3 using namespace std;
 4 const int qs=3e5+7;
 5 const ll mod=998244353;
 6 ll dp[qs],f[qs];
 7 ll n,m;
 8 string s[qs];
 9 int main(){
10     std::ios::sync_with_stdio(false);
11     cin>>n>>m;
12     for(int i=0;i<n;++i) cin>>s[i];
13     dp[1]=dp[0]=0; f[0]=1,f[1]=2;
14     for(int i=2;i<=qs-6;++i){
15         dp[i]=((dp[i-1]+f[i-2])%mod+dp[i-2]*2%mod)%mod;
16         f[i]=2*f[i-1]%mod;
17     }
18     ll cnt=0,a1=0,a2=0,ans,sum=0;
19     for(int i=0;i<n;++i) 
20     for(int j=0;j<m;++j) if(s[i][j]=='o') sum++;
21     for(int i=0;i<n;++i){
22         for(int j=0;j<m;++j){
23             if(s[i][j]=='o') ++cnt;
24             if(s[i][j]!='o'||j==m-1){
25                 if(cnt==1){
26                     cnt=0; continue;
27                 }
28                  a1=a1+dp[cnt]%mod*f[sum-cnt]%mod;
29                 a1%=mod;
30                 cnt=0;
31             }
32         }
33     }
34     cnt=0;
35     for(int j=0;j<m;++j){
36         for(int i=0;i<n;++i){
37             if(s[i][j]=='o') ++cnt;
38             if(s[i][j]!='o'||i==n-1){
39                 if(cnt==1){
40                      cnt=0; continue;
41                 }
42                  a2=a2+dp[cnt]%mod*f[sum-cnt]%mod;
43                  a2%=mod;
44                 cnt=0;
45             }
46         }
47     }
48     ans=(a1+a2)%mod;
49     cout<<ans<<"
";
50     return 0;
51 }

//QAQ

原文地址:https://www.cnblogs.com/Suki-Sugar/p/14663353.html