AT_arc108_d

挺有意思的题。

一开始看到 n1000n\le 1000 想的是一个类似区间 dp 的东西,但是没写完就发现这样完全不能去重。

于是考虑推一些性质。一开始序列是 AB,不妨设 cAB=Ac_{AB}=A,另一种情况大概是对称的。则序列会变成 AAB。此时发现,右半边仍然是 AB,怎么做都只能再增加一个 A。所以只用考虑左半边的 AA

同时注意到这要求最终的 sn1=As_{n-1}=A

  • 如果 cAA=Ac_{AA}=A,那么最终序列就只有 AAA...AB 这一种情况。

  • 否则若 cBA=Bc_{BA}=B,则可以发现,任何一个 s1=A,sn1=A,sn=Bs_1=A,s_{n-1}=A,s_n=B 的序列都可以构造出来,方法是先不管开头的 A 和结尾的 B ,每次找到最后一个连续段,先把这个连续段的第一个位置填上,再往后填。故方案数为 2n32^{n-3}

  • 否则还是类似上面的,但是此时不能有两个连续的 B,因为 cAB=cBA=Ac_{AB}=c_{BA}=A。这是一个经典计数问题,设 fnf_n 为长为 nn 的序列的方案数,则 fff0=1,f1=2f_0=1,f_1=2 的斐波那契数列。方案数为 fn3f_{n-3}

cAB=Bc_{AB}=B 的答案是类似的,对称地推一下即可。

code:

int n,m,a[4],f[N];
il int Mod(int x,int y){
	return x+y>=mod?x+y-mod:x+y;
}
il int qpow(int x,int y){
	int ret=1;
	while(y){
		if(y&1){
			ret=1ll*ret*x%mod;
		}
		x=1ll*x*x%mod,y>>=1;
	}
	return ret;
}
void Yorushika(){
	read(n);
	if(n==2){
		puts("1");
		return;
	}
	rep(i,0,3){
		char s[7];scanf("%s",s);
		a[i]=s[0]-'A';
	}
	f[0]=1,f[1]=2;
	rep(i,2,n){
		f[i]=Mod(f[i-1],f[i-2]);
	}
	if(a[1]==0){
		if(a[0]==0){
			puts("1");
		}else{
			if(a[2]==1){
				printf("%d\n",qpow(2,n-3));
			}else{
				printf("%d\n",f[n-3]);
			}
		}
	}else{
		if(a[3]==1){
			puts("1");
		}else{
			if(a[2]==0){
				printf("%d\n",qpow(2,n-3));
			}else{
				printf("%d\n",f[n-3]);
			}
		}
	}
}
signed main(){
	int t=1;
	//read(t);
	while(t--){
		Yorushika();
	}
}