这道题我只会子集和变换优化的sb暴力(什么轮廓线插头都忘光了…)
考虑到合法状态的稀疏性(其实是你自己不会证明吧……),就可以放心暴力啦;
#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
const int mod=1e9+7;
const int N=5e4+7;
const int M=5e5+7;
void upd(int& x,int y){
x+=y;if(x>=mod)x-=mod;
}
int qpow(int a,int b){
int res=1,aa=a;
for(;b;b>>=1){if(b&1)res=1ll*res*aa%mod;aa=1ll*aa*aa%mod;}
return res;
}
int n,m,c,T,mo[2][17],b[17],stk[N],top;
vector<int> tu[N];
char s[2][17];
struct E{
int to,w,next;E(int to=0,int w=0,int next=0):to(to),w(w),next(next){}
}edge[M];
int head[N],tot;
void add(int x,int y,int w){
edge[++tot]=E(y,w,head[x]);head[x]=tot;
}
int f[2][N],now;
int trans(int x,int op){
rep(i,0,m-1)b[i]=x%3,x/=3;
int res=0;
rep(i,0,m-c){int j;
for(j=0;j<c && mo[op][j]==b[i+j];j++);
if(j==c)res|=(1<<(i+c-1));
}return res;
}
void init(){
int S=qpow(3,m)-1;
rep(i,0,S){
int k1=trans(i,0);
int k2=trans(i,1);
tu[k1].push_back(k2);
}S=(1<<m)-1;
top=0;
rep(i,0,S){
int lim=tu[i].size();
if(lim){
f[0][i]=lim;
sort(tu[i].begin(),tu[i].end());
stk[++top]=i;
int last=tu[i][0],cc=1;
rep(j,1,lim-1){
if(tu[i][j]==last)cc++;
else{
add(i,last,cc);
last=tu[i][j],cc=1;
}
}
add(i,last,cc);
}
}
}
void change(int op){
int S=(1<<m)-1;
rep(i,0,m-1){
rep(j,0,S){
if(j&(1<<i))upd(f[op][j],f[op][j^(1<<i)]);
}
}
}
void dp(){
now=0;
int S=(1<<m)-1;
rep(i,1,n-1){
now^=1;
memset(f[now],0,sizeof(f[now]));
change(now^1);
rep(j,1,top){
int u=stk[j];
for(int kk=head[u];kk;kk=edge[kk].next){
int v=edge[kk].to;
int w=edge[kk].w;
upd(f[now][u],1ll*w*f[now^1][S^v]%mod);
}
}
}change(now);
int ans=qpow(3,n*m);
upd(ans,mod-f[now][S]);
printf("%d\n",ans);
}
int main(){
scanf("%d%d%d%d",&n,&m,&c,&T);
while(T--){
rep(i,0,(1<<m)-1)tu[i].clear();
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
tot=0;
scanf("%s%s",s[0],s[1]);
rep(i,0,c-1)if(s[0][i]=='B')mo[0][i]=1;else if(s[0][i]=='W')mo[0][i]=2;else mo[0][i]=0;
rep(i,0,c-1)if(s[1][i]=='B')mo[1][i]=1;else if(s[1][i]=='W')mo[1][i]=2;else mo[1][i]=0;
init();
dp();
}
}