sol:
考虑到汉诺塔 游戏。中间显然会有一个状态,使得最大的盘子在a柱,目标是c,其他盘子都在b。那我们考虑把这个状态称为中间状态。那么现在考虑怎么把起始的盘子弄到这个中间状态,再把终止的盘子弄到这个中间状态。显然对于每一个最大的盘子,他在对应的位置上我们就不管他了,否则他在a,目标是c,肯定其他盘子叠到b,然后a->c,再花2^n-1步把叠好的盘子移到c。这个步数是经典结论。
结果我们样例都过不了。我们发现还有一种中间状态,他可以是最大的盘子在a,目标是c,先把其他盘子移到c,然后a到b,再把其他盘子到a,最大的盘子再到c。那就是最后还要再花2^{n-1}+1步
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+7;
int n,m,ans1[N],ans2[N],pos1[N],pos2[N];
inline void calc(int *ans,int *pos,int id)
{
for(int i=n-1;i>=1;--i)
{
if(pos[i]!=id)
{
ans[i-1]++;
id=6-pos[i]-id;
}
}
}
inline void simplex(int *a)
{
for(int i=1;i<=n;++i) a[i]+=a[i-1]/2,a[i-1]&=1;
}
inline bool cmp(int *a,int *b)
{
for(int i=n;i>=1;--i)
{
if(a[i]==b[i]) continue;
if(a[i]) return 0;
else return 1;
}
return 0;
}
const int pyz=998244353;
int Pow[N];
inline void print(int *a)
{
ll ans=0;
Pow[0]=1;
for(int i=1;i<=n;++i) Pow[i]=Pow[i-1]*2%pyz;
for(int i=0;i<=n;++i) ans=(ans+(ll)a[i]*Pow[i]%pyz)%pyz;
cout<<ans;
}
int main()
{
// freopen("b.in","r",stdin);
cin>>n;
for(int i=1;i<=3;++i)
{
cin>>m;
for(int j=1;j<=m;++j)
{
int x;
scanf("%d",&x);
pos1[x]=i;
}
}
for(int i=1;i<=3;++i)
{
cin>>m;
for(int j=1;j<=m;++j)
{
int x;
scanf("%d",&x);
pos2[x]=i;
}
}
while(pos1[n]==pos2[n]) --n;
if(!n)
{
printf("0\n");
return 0;
}
calc(ans1,pos1,6-pos1[n]-pos2[n]);
calc(ans1,pos2,6-pos1[n]-pos2[n]);
ans1[0]++;
simplex(ans1);
calc(ans2,pos1,pos2[n]);
calc(ans2,pos2,pos1[n]);
ans2[n-1]++;ans2[0]++;
simplex(ans2);
if(cmp(ans1,ans2)) print(ans1);
else print(ans2);
}