Global Round 18
场上 ABCE,准确来说 ABE
AB 略
C. Menorah
D. X(or)-mas Tree
E. Purple Crayon
F. LEGOndary Grandmaster
都说是一道好题,确实是一道好题。我现在对 tzc 膜拜得五体投地。
先考虑判断,根据套路,我们反转偶数位置得到两个新的串,此时操作相当于交换相邻,并且相同交换则无意义。
此时可行当且仅当两串中 \(1\) 的个数相同,然后我们考虑计数。
这时我们显然的式子:\(\sum\limits_{i=1}^c |poss_i-post_i|\),直接硬上 \(dp\) 肯定可以。
或者我们有一个更飘逸的式子:\(\sum\limits_{i=1}^n |pres_i-pret_i|\),正确性显然,做法显然。
#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
const int N=2e3+5;
int n,m,f[N][N<<1],g[N][N<<1],S[N],T[N];
string s,t;
inline void add(int &x,int y){x=(x+y>=mod?x+y-mod:x+y);}
inline void solve(){
n=read();cin>>s>>t;
for(int i=1;i<=n;i++){
S[i]=s[i-1]=='?'?-1:s[i-1]-'0';
T[i]=t[i-1]=='?'?-1:t[i-1]-'0';
if(i%2==0&&S[i]>=0)S[i]^=1;
if(i%2==0&&T[i]>=0)T[i]^=1;
}f[0][n]=g[n+1][n]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=n+n;j++){
if(S[i]==-1&&T[i]==-1){
add(f[i][j],f[i-1][j]);
add(f[i][j],f[i-1][j]);
if(j<n+n)add(f[i][j],f[i-1][j+1]);
if(j>0)add(f[i][j],f[i-1][j-1]);
}else if(S[i]==-1){
if(j>=T[i])add(f[i][j],f[i-1][j-T[i]]);
add(f[i][j],f[i-1][j+1-T[i]]);
}else if(T[i]==-1){
if(j+S[i])add(f[i][j],f[i-1][j+S[i]-1]);
add(f[i][j],f[i-1][j+S[i]]);
}else if(j+S[i]>=T[i])add(f[i][j],f[i-1][j+S[i]-T[i]]);
}
for(int i=n;i>=1;i--)
for(int j=0;j<=n+n;j++){
if(S[i]==-1&&T[i]==-1){
add(g[i][j],g[i+1][j]);
add(g[i][j],g[i+1][j]);
if(j<n+n)add(g[i][j],g[i+1][j+1]);
if(j>0)add(g[i][j],g[i+1][j-1]);
}else if(S[i]==-1){
if(j>=T[i])add(g[i][j],g[i+1][j-T[i]]);
add(g[i][j],g[i+1][j+1-T[i]]);
}else if(T[i]==-1){
if(j+S[i])add(g[i][j],g[i+1][j+S[i]-1]);
add(g[i][j],g[i+1][j+S[i]]);
}else if(j+S[i]>=T[i])add(g[i][j],g[i+1][j+S[i]-T[i]]);
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
ans=(ans+1ll*f[i][n+j]*g[i+1][n-j]%mod*j)%mod;
ans=(ans+1ll*f[i][n-j]*g[i+1][n+j]%mod*j)%mod;
}
printf("%d\n",ans);
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+n;j++)
f[i][j]=g[i][j]=0;
}
int main(){
int o=read();
while(o--)solve();
return 0;
}