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;
}

posted @ 2021-07-14 20:57  ファイナル  阅读(43)  评论(0编辑  收藏  举报