CF1511E Colorings and Dominoes
CF1511E Colorings and Dominoes
这里提供一个不同的思路
我们考虑对于每对相邻的位置,单独地计算它的贡献
先只考虑横着的情况
我们发现只有当钦定的方格两旁红色格子数同偶时才会计入答案,贡献1(\((RR)\underline{(RR)}(RR)\))
而异奇偶时贡献1/2(\((O\underline{(RR)}(RR)\)与\((R\underline{R)O}(RR)\)同样为最大答案)
而同奇时不计入答案(\((R\underline{R)(R}R)\))
所以设此对格子\((x,y)(x,y+1)\)左右能延伸到的最长空位(含自己)分别为\(L,R\)
对于每种情况单独维护,先考虑同偶时贡献(设总空位数为\(cnt\)):
\(\sum_{i=2k+1,i\in[1,L]}\sum_{j=2t+1,j\in[1,R]}2^{cnt-i-j-[i\not= L]-[j\not =R]}\)
为什么呢?因为我们相当于枚举了这段红块的长度,而红块的两旁需要为空或者蓝色
直接操作发现是\(O((nm)^3)\)的,考虑优化
\[\sum_{i=2k+1,i\in[1,L]}\sum_{j=2t+1,j\in[1,R]}2^{cnt-i-j-[i\not= L]-[j\not =R]}
\\=2^{cnt}\left(\sum_{i=2k+1,i\in[1,L]}2^{-i-[i\not= L]}\right)\left(\sum_{j=2t+1,j\in[1,R]}2^{-j-[j\not =R]}\right)
\]
这里已经是\(O(nm(n+m))\)了,因为发现遍历过程中每次只会\(++L,--R\)以及在每一空段的开头\(O(len)\)地处理,所以每次移动只会更改\(sigma\)内2项的值,可以动态维护括号内的累和
这样时间复杂度\(O(nm)\),这里由于赛时敲傻了,所以打的比较复杂,实际上可以非常简单的
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
T t=0;
char k;
bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define mod 998244353
# define inv2 499122177ll
char *str[300005];
int n,m;
ll qkpow(ll n,int m){
ll t=1;
for(;m;m>>=1,n=n*n%mod)
if(m&1)t=t*n%mod;
return t;
}ll Invp[300010];
ll Qkpow(int x){return Invp[-x];}
int main(){
n=read,m=read;*str=new char[m+5]();
str[n+1]=new char[m+5]();
for(int i=1;i<=n;++i){
str[i]=new char[m+5]();
scanf("%s",str[i]+1);
}int cnt=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(str[i][j]=='o')
++cnt;
Invp[0]=1;
for(int i=1;i<=n+m+5;++i)Invp[i]=Invp[i-1]*inv2%mod;
ll ans=0,t1,t2,t3,t4,va=qkpow(2,cnt);
for(int i=1;i<=n;++i)
for(int j=1,l=0,r=0;j<m;++j,++l,--r)
if(str[i][j]=='o'&&str[i][j+1]=='o'){
if(r<=0){
l=r=0;
for(int k=j;str[i][k]=='o';--k)++l;
for(int k=j+1;str[i][k]=='o';++k)++r;
t1=0,t2=0,t3=0,t4=0;
for(int o=1;o<=l;o+=2)
(t1+=Qkpow(-o-(l!=o)))%=mod;
for(int p=1;p<=r;p+=2)
(t2+=Qkpow(-p-(r!=p)))%=mod;
for(int o=2;o<=l;o+=2)
(t3+=Qkpow(-o-(l!=o)))%=mod;
for(int p=2;p<=r;p+=2)
(t4+=Qkpow(-p-(r!=p)))%=mod;
}else{
int o=l-1;if(~o&1)--o;
t1=(t1-Qkpow(-o-(l-1!=o))+Qkpow(-o-(l!=o)))%mod;
o=l-1;if(o&1)--o;
t3=(t3-Qkpow(-o-(l-1!=o))+Qkpow(-o-(l!=o)))%mod;
if(l&1)t1=(t1+Qkpow(-l))%mod;
else t3=(t3+Qkpow(-l))%mod;
int p=r-1;if(~p&1)++p;
t2=(t2-Qkpow(-p-(r+1!=p))+Qkpow(-p-(r!=p)))%mod;
p=r-1;if(p&1)++p;
t4=(t4-Qkpow(-p-(r+1!=p))+Qkpow(-p-(r!=p)))%mod;
if(r&1)t4=(t4-Qkpow(-r-1))%mod;
else t2=(t2-Qkpow(-r-1))%mod;
}
ans=(ans+(t1*t2+t1*t4%mod*inv2+t2*t3%mod*inv2)%mod*va)%mod;
}
for(int j=1;j<=m;++j)
for(int i=1,l=0,r=0;i<n;++i,++l,--r)
if(str[i][j]=='o'&&str[i+1][j]=='o'){
if(r<=0){
l=r=0;
for(int k=i;str[k][j]=='o';--k)++l;
for(int k=i+1;str[k][j]=='o';++k)++r;
t1=0,t2=0,t3=0,t4=0;
for(int o=1;o<=l;o+=2)
(t1+=Qkpow(-o-(l!=o)))%=mod;
for(int p=1;p<=r;p+=2)
(t2+=Qkpow(-p-(r!=p)))%=mod;
for(int o=2;o<=l;o+=2)
(t3+=Qkpow(-o-(l!=o)))%=mod;
for(int p=2;p<=r;p+=2)
(t4+=Qkpow(-p-(r!=p)))%=mod;
}else{
int o=l-1;if(~o&1)--o;
t1=(t1-Qkpow(-o-(l-1!=o))+Qkpow(-o-(l!=o)))%mod;
o=l-1;if(o&1)--o;
t3=(t3-Qkpow(-o-(l-1!=o))+Qkpow(-o-(l!=o)))%mod;
if(l&1)t1=(t1+Qkpow(-l))%mod;
else t3=(t3+Qkpow(-l))%mod;
int p=r-1;if(~p&1)++p;
t2=(t2-Qkpow(-p-(r+1!=p))+Qkpow(-p-(r!=p)))%mod;
p=r-1;if(p&1)++p;
t4=(t4-Qkpow(-p-(r+1!=p))+Qkpow(-p-(r!=p)))%mod;
if(r&1)t4=(t4-Qkpow(-r-1))%mod;
else t2=(t2-Qkpow(-r-1))%mod;
}
ans=(ans+(t1*t2+t1*t4%mod*inv2+t2*t3%mod*inv2)%mod*va)%mod;
}cout<<(ans+mod)%mod;
return 0;
}
因果乃旋转纺车,光彩之多面明镜
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存