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

G. Maximum Adjacent Pairs

H. Reindeer Games

posted @ 2022-04-11 17:52  syzf2222  阅读(25)  评论(0编辑  收藏  举报